当绑定到Array元素的控件更改值时,不会调用Setter

时间:2013-10-07 21:51:48

标签: c# .net wpf xaml mvvm

我是WPF和绑定的新手,我想看看是否有办法在数组元素和控件之间进行双向绑定:

我的ViewModel有一个如下属性:

public ObservableCollection<MeaseurementValue> MeasurementValues
        {
            get
            {
                return Config.MeasurementValues;
            }
            set
            {
                if (value == null) return;
                Config.MeasurementValues = value;
                OnPropertyChanged("MeasurementValues");
                QpatConfig.SerializeConfigFile(Config,
                    Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)) + "//Qualcomm//QPAT//qpat.config");              
            }
        }

其中MeasurementValues的定义如下:

public class MeaseurementValue
    {
      public string TestName { get; set; }
      public int value { get;set; }
    }

Xaml看起来如下:

 <TextBox HorizontalAlignment="Left" Grid.Column="1"   Grid.Row="1"   Height="23" Margin="14,20,0,0" TextWrapping="Wrap" Text="{Binding MeasurementValues[0].value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="124"  />

因此xaml中的元素绑定到ViewModel中的Arrayelement。但是当我在文本控件中更改该属性时,它不会调用ViewModel的setter。

我还改变了我的代码,即数组中的evey元素也是必须通知的,所以看起来如下:

public class MeaseurementValue : INotifyPropertyChanged
    {
      public event PropertyChangedEventHandler PropertyChanged;
      public string TestName { get; set; }    

      private int _value;
      public int value
      {
          get { return _value; }
          set { _value = value; OnPropertyChanged("value"); }
      }

      void OnPropertyChanged(string propertyName)
      {
          var handler = PropertyChanged;
          if (handler != null)
          {
              handler(this, new PropertyChangedEventArgs(propertyName));
          }
      }
    }

但那也行不通

我们与Arrays有什么不同,与原始类型相反?

1 个答案:

答案 0 :(得分:2)

setter被调用,而不是你期望的那个。在双向绑定中,只更新路径中的最后一个属性(在目标 - >源方向上)。

想想这样 - 如果你用C#编写它,你会发生什么?

MeasurementValues[0].value = 1;

这里发生的是首先调用MeasurementValues getter ,然后调用数组索引器的 getter ,但 setter 属于value属性。所以没有理由让数组的setter被调用。你是远离MeasurementValues setter的两个属性访问者。即使你写了

MeasurementValues[0] = new MeasurementValue();

不会调用MeasurementValues setter。仅

MeasurementValues = new ObservableCollection<MeaseurementValue>();

会导致你所指的setter被调用。这与绑定完全相同。属性路径中的 last 项是双向绑定中使用的唯一setter。在您的情况下,它是value属性。

如果要在每次设置value属性时保存配置,您可以:

  • ValueChanged中创建MeaseurementValue事件,并在创建每个项目时将其挂钩
  • 使用某些发布/订阅机制(例如Prism的事件聚合器)来发布值已更改