WPF:什么可能导致绑定源不被更新?

时间:2009-10-30 16:48:26

标签: wpf data-binding

我有一种情况我不确定如何调试。我希望有人可以建议为什么它可能不起作用并指出我正确的方向。

我有来自数据库的TIFF图像,该图像作为System.Data.Linq.Binary类型的属性公开。我想在ItemsControl中显示来自该TIFF图像的各个帧,因此我编写了一个采用二进制数据类型并返回ObservableCollection个BitmapFrame的转换器。我使用转换器以及ItemsControl.ItemsSource"Mode=TwoWay""UpdateSourceTrigger=PropertyChanged"绑定到二进制属性。

图像显示工作正常。问题是,如果我向集合添加一个框架,则显示更新,但该更改不会传输回源对象中的Binary属性。我的转换器中的ConvertBack()方法永远不会被调用(告诉我绑定永远不会尝试更新源)。如果我手动拨打BindingExpression.UpdateSource(),就好像它已设置为"UpdateSourceTrigger=Explicit"一样,二进制属性确实正确更新。

因此,如果为"Mode=TwoWay""UpdateSourceTrigger=PropertyChanged"设置了绑定,并且对象实现了INotifyPropertyChangedObserverableCollection执行了),为什么绑定实际上不会尝试更新来源?

谢谢!

2 个答案:

答案 0 :(得分:2)

我已成功使用此博客文章来帮助调试绑定问题。特别是“TraceLevel”方法。

Bea Stollnitz - How can I debug WPF bindings?

答案 1 :(得分:2)

这是因为对于TwoWay绑定,WPF仅检测属性何时获取新值,而不是当属性引用的对象发生更改时。

在您的情况下,您的属性包含转换器创建的ObservableCollection。尽管ObservableCollection的内容已经被修改,并且它触发了INotifyPropertyChanged,但绑定属性本身并没有改变:它仍然像以前一样引用相同的ObservableCollection。因此,不会触发WPF DataBinding,也不会更新您的源。

当您手动调用UpdateSource()时,它会强制ObservableCollection通过您的转换器并返回到您的数据对象,因此它可以正常工作。

获得所需行为的最简单方法是:

  1. 不是绑定到数据字段,而是绑定到数据对象,并在转换器中提取所需的字段(如果要创建可以访问任何字段的通用转换器,请将该字段作为参数传递)

  2. 在构造ObservableCollection的转换器中,添加一个CollectionChanged事件,该事件会在触发时更新原始对象。

  3. 以下是代码中的一般概念:

      public MyConverter : IValueConverter
      {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
          PropertyInfo property = object.GetType().GetProperty((string)parameter);
    
          var coll = BinaryToCollection((Binary)property.GetValue(object, null));
    
          coll.CollectionChanged += (sender, e) =>
          {
            property.SetValue(object, CollectionToBinary(coll));
          };
          return coll;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
          throw new NotImplementedException();
        }
    
        private ObservableCollection<SomeType> BinaryToCollection(Binary data)
        {
          // conversion details here
        }
    
        private Binary CollectionToBinary(ObservableCollection<SomeType> coll)
        {
          // conversion details here
        }
    
      }
    

    在这种情况下,您的绑定将从

    更改
     <ItemsControl ItemsSource="{Binding something.property, Mode=TwoWay, Converter={...}}"
    

      <ItemsControl ItemsSource="{Binding something, Converter={...}}"
    

    转换器参数是属性名称

    希望这有帮助!