我有一种情况我不确定如何调试。我希望有人可以建议为什么它可能不起作用并指出我正确的方向。
我有来自数据库的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"
设置了绑定,并且对象实现了INotifyPropertyChanged
(ObserverableCollection
执行了),为什么绑定实际上不会尝试更新来源?
谢谢!
答案 0 :(得分:2)
我已成功使用此博客文章来帮助调试绑定问题。特别是“TraceLevel”方法。
答案 1 :(得分:2)
这是因为对于TwoWay绑定,WPF仅检测属性何时获取新值,而不是当属性引用的对象发生更改时。
在您的情况下,您的属性包含转换器创建的ObservableCollection。尽管ObservableCollection的内容已经被修改,并且它触发了INotifyPropertyChanged,但绑定属性本身并没有改变:它仍然像以前一样引用相同的ObservableCollection。因此,不会触发WPF DataBinding,也不会更新您的源。
当您手动调用UpdateSource()时,它会强制ObservableCollection通过您的转换器并返回到您的数据对象,因此它可以正常工作。
获得所需行为的最简单方法是:
不是绑定到数据字段,而是绑定到数据对象,并在转换器中提取所需的字段(如果要创建可以访问任何字段的通用转换器,请将该字段作为参数传递)
在构造ObservableCollection的转换器中,添加一个CollectionChanged事件,该事件会在触发时更新原始对象。
以下是代码中的一般概念:
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={...}}"
转换器参数是属性名称
希望这有帮助!