代码之家  ›  专栏  ›  技术社区  ›  Andrew

与itemscontrol的twoway绑定

  •  6
  • Andrew  · 技术社区  · 16 年前

    我正在尝试编写一个具有itemsControl的用户控件,其中itemsTemplate包含一个允许twoway绑定的文本框。但是,我一定是在代码的某个地方犯了一个错误,因为绑定似乎只在模式=单向的情况下工作。这是我项目的一个非常简单的摘录,但它仍然包含问题:

    <UserControl x:Class="ItemsControlTest.UserControl1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="300" Width="300">
        <Grid>
            <StackPanel>
                <ItemsControl ItemsSource="{Binding Path=.}"
                              x:Name="myItemsControl">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBox Text="{Binding Mode=TwoWay,
                                                    UpdateSourceTrigger=LostFocus,
                                                    Path=.}" />
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
                <Button Click="Button_Click"
                        Content="Click Here To Change Focus From ItemsControl" />
            </StackPanel>
        </Grid>
    </UserControl>
    

    下面是上述控件的代码隐藏:

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Collections.ObjectModel;
    
    namespace ItemsControlTest
    {
        /// <summary>
        /// Interaction logic for UserControl1.xaml
        /// </summary>
        public partial class UserControl1 : UserControl
        {
            public ObservableCollection<string> MyCollection
            {
                get { return (ObservableCollection<string>)GetValue(MyCollectionProperty); }
                set { SetValue(MyCollectionProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for MyCollection.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty MyCollectionProperty =
                DependencyProperty.Register("MyCollection",
                                            typeof(ObservableCollection<string>),
                                            typeof(UserControl1),
                                            new UIPropertyMetadata(new ObservableCollection<string>()));
    
            public UserControl1()
            {
                for (int i = 0; i < 6; i++)
                    MyCollection.Add("String " + i.ToString());
    
                InitializeComponent();
    
                myItemsControl.DataContext = this.MyCollection;
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                // Insert a string after the third element of MyCollection
                MyCollection.Insert(3, "Inserted Item");
    
                // Display contents of MyCollection in a MessageBox
                string str = "";
                foreach (string s in MyCollection)
                    str += s + Environment.NewLine;
                MessageBox.Show(str);
            }
        }
    }
    

    最后,这里是主窗口的XAML:

    <Window x:Class="ItemsControlTest.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:src="clr-namespace:ItemsControlTest"
            Title="Window1" Height="300" Width="300">
        <Grid>
            <src:UserControl1 />
        </Grid>
    </Window>
    

    好吧,这就是一切。我不知道为什么编辑文本框。窗口中的文本属性似乎没有更新代码隐藏中绑定的源属性,即myCollection。点击按钮会让我的问题直视我的脸;)请帮助我了解我哪里出错了。

    谢谢!

    安得烈

    1 回复  |  直到 14 年前
        1
  •  8
  •   Charlie    16 年前

    好吧,我相信引起这个问题的原因是你直接与 String . 字符串是 不变的 因此,当您更改文本时,它无法更改 ObservableCollection . 要解决这个问题,您只需创建一个模型类来保存字符串数据,然后绑定 TextBox.Text 到该类内的属性。下面是一个例子:

    public partial class BindingToString : Window
    {
        public BindingToString()
        {
            MyCollection = new ObservableCollection<TestItem>();
    
            for (int i = 0; i < 6; i++)
                MyCollection.Add(new TestItem("String " + i.ToString()));
    
            InitializeComponent();
    
            myItemsControl.DataContext = this.MyCollection;
        }
    
        public ObservableCollection<TestItem> MyCollection
        {
            get;
            set;
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Display contents of MyCollection in a MessageBox
            string str = "";
            foreach (TestItem s in MyCollection)
                str += s.Name + Environment.NewLine;
            MessageBox.Show(str);
        }
    }
    
    public class TestItem
    {
        public string Name
        {
            get;
            set;
        }
    
        public TestItem(string name)
        {
            Name = name;
        }
    }
    

    请注意,我将您的依赖属性更改为标准属性-没有理由使集合成为依赖属性。除此之外,唯一的区别是包含包装类 TestItem 保存字符串数据。

    <Window x:Class="TestWpfApplication.BindingToString"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="BindingToString " Height="300" Width="300">
    <Grid>
        <StackPanel>
            <ItemsControl ItemsSource="{Binding}"
                          x:Name="myItemsControl">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
            <Button Click="Button_Click"
                    Content="Click Here To Change Focus From ItemsControl" />
        </StackPanel>
    </Grid>
    

    现在 TextBox 绑定到 Name 路径上 测试项目 ,并且此绑定按预期工作并修改集合。