Xaml将文本框双向绑定到可观察集合

时间:2014-01-14 21:33:26

标签: xaml data-binding mvvm windows-phone-8 observablecollection

在我的WP8应用程序中,我有一个类,它有一个名为Matrix的ObservableCollection<ObservableCollection<int>>属性。

我想使用项目控件显示这些矩阵。

 <ItemsControl ItemsSource="{Binding FirstMatrix.Matrix}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ItemsControl ItemsSource="{Binding}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal"></StackPanel>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding}" />
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

代码就显示而言起作用(它用零填充,这是一个默认值)。但我也想允许TextBox中的更改,这些更改将反映在Matrix属性中 - 现在TextBoxes无法更改,因为它的值被绑定到Matrix单元格的一种方式。我尝试设置<TextBox Text="{Binding Mode=TwoWay}" />或类似但它似乎不起作用。 任何想法应该如何绑定数据?

编辑: 我已经实现了INotifyPropertyChanged。 这是我班级的一部分:

public partial class CalcMatrix : INotifyPropertyChanged
    {
        public ObservableCollection<ObservableCollection<int>> Matrix 
        { 
            get { return _matrix; }
            set
            {
                _matrix = value;
                OnPropertyChanged("Matrix");
            } 
        }
        private ObservableCollection<ObservableCollection<int>> _matrix;

        private void OnPropertyChanged(string argName)
        {
            var handler = PropertyChanged;
            if(handler != null)
                handler(this, new PropertyChangedEventArgs(argName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

我认为TexBoxes不改变的原因是因为绑定是单向的 - Text总是在Matrix内部。我相信我应该以某种方式改变XAML绑定到TwoWay或其他东西,但不知道如何。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

它没有工作的原因是itemsource是一个Matrix列表,你没有对列表进行任何更改,就像添加或从列表中删除一样,而是改变列表中存在的项的属性我假设你正在使用ObservableCollection .... 因此,您需要实现一个INotifyPropertyChanged接口,告诉用户界面我已更改,请自行更新....

 class YourClass : INotifyPropertyChanged
{

 private string yourProperty;
 public string YourPropety{
   get{ 
        return yourProperty; 
     }
   set{
         if (value != this.yourProperty)
            {
                this.yourProperty = value;
                NotifyPropertyChanged();
            }
    }
 }       

 public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        } 
    }
 }

答案 1 :(得分:1)

双向模式绑定需要路径(为什么?see this SO answer),所以你不能像{Binding Mode=TwoWay}那样做,它必须像{Binding SomePath, Mode=TwoWay}。因此,在这种情况下,您必须将矩阵项包装为某个类而不是plain int,并将该int作为该类的属性值。

//your Matrix property type become:
...
public ObservableCollection<ObservableCollection<MatrixElement>> Matrix
...

//MatrixElement class is something like:
public class MatrixElement : INotifyPropertyChanged
{
    private int _value;
    public int Value
    {
        get { return _value; }
        set { 
                _value = value; 
                OnPropertyChanged("Value"); 
            }
    }

    ....
}

//then you can bind TextBox in two way mode
...
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <TextBox Text="{Binding Value, Mode=TwoWay}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>
...