与ItemsControl的双向绑定 [英] TwoWay Binding With ItemsControl

查看:77
本文介绍了与ItemsControl的双向绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个具有ItemsControl的用户控件,该控件的ItemsTemplate包含一个允许TwoWay绑定的TextBox.但是,我肯定在我的代码中的某个地方犯了一个错误,因为绑定似乎仅在Mode = OneWay的情况下起作用.这是我的项目的相当简化的摘录,但仍然包含问题:

I'm trying to write a user control that has an ItemsControl, the ItemsTemplate of which contains a TextBox that will allow for TwoWay binding. However, I must be making a mistake somewhere in my code, because the binding only appears to work as if Mode=OneWay. This is a pretty simplified excerpt from my project, but it still contains the problem:

<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>

以下是上述控件的代码:

Here's the code behind for the above control:

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:

And finally, here's the xaml for the main window:

<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>

好,这就是全部.我不确定为什么在窗口中编辑TextBox.Text属性似乎没有更新后面代码(即MyCollection)中绑定的源属性.单击按钮几乎会导致问题盯着我;)请帮助我了解我要去哪里.

Well, that's everything. I'm not sure why editing the TextBox.Text properties in the window does not seem to update the source property for the binding in the code behind, namely MyCollection. Clicking on the button pretty much causes the problem to stare me in the face;) Please help me understand where I'm going wrong.

感谢!

安德鲁

推荐答案

好吧,我相信导致此问题的原因是您直接绑定到String.字符串在C#中是不可变的,因此,当您更改文本时,它不能更改ObservableCollection中的基础字符串.要解决此问题,您可以做的只是创建一个模型类来保存字符串数据,然后将TextBox.Text绑定到该类中的属性.这是一个示例:

Ok I believe what is causing this problem is that you are binding directly to a String . Strings are immutable in C# and thus when you change the text, it cannot change the underlying string in the ObservableCollection. What you can do to get around this problem is simply create a model class to hold the string data, and then bind the TextBox.Text to a property inside that class. Here is an example:

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来保存字符串数据.

Notice that I changed your dependency property to a standard property- there is no reason to make the collection a dependency property. Besides that the only difference is the inclusion of the wrapper class TestItem to hold the string data.

<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已绑定到TestItem上的Name路径,并且此绑定可以正常工作并按预期修改集合.

Now the TextBox is bound to the Name path on TestItem, and this binding works and modifies the collection as expected.

这篇关于与ItemsControl的双向绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆