WPF:什么会导致绑定源不被更新?
我有一种情况,我不知道如何调试。我希望有人可以建议为什么它可能无法正常工作,并指向正确的方向。WPF:什么会导致绑定源不被更新?
我有从被露出System.Data.Linq.Binary
类型的属性的数据库中的TIFF图像。我想在ItemsControl
所以我写了一个转换器,采用二进制数据类型,并返回BitmapFrames的ObservableCollection
显示从TIFF图像的单个帧。我使用的是转换器"Mode=TwoWay"
和"UpdateSourceTrigger=PropertyChanged"
沿着结合ItemsControl.ItemsSource
的二进制属性。
图像的显示工作正常。问题是,如果我向显示更新的集合添加一个框架,但该更改不会传回到源对象中的二进制属性。我的转换器中的ConvertBack()
方法永远不会被调用(表明绑定从来没有尝试更新源代码)。如果我手动打电话给BindingExpression.UpdateSource()
就好像它设置为"UpdateSourceTrigger=Explicit"
Binary属性确实更新正确。
因此,如果设置约束力的"Mode=TwoWay"
和"UpdateSourceTrigger=PropertyChanged"
和对象实现INotifyPropertyChanged
(其中ObserverableCollection
如此),为什么不结合实际尝试更新的来源?
谢谢!
这是因为发生了双向绑定,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={...}}"
与转换参数是物业名称
希望这有助于!
谢谢雷!我遵循你所说的话,但我必须说我很惊讶。这不是我如何将这个过程想象为工作。 我很欣赏你对解决方案的建议,但它不适合我的情况。我最终通过观察NotifyCollectionChangedEvents并使用它们来触发BindingExpression.UpdateSource()来解决它。这种方法更适合我的情况。 – 2009-10-31 05:02:42