2009-10-30 95 views
1

我有一种情况,我不知道如何调试。我希望有人可以建议为什么它可能无法正常工作,并指向正确的方向。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如此),为什么不结合实际尝试更新的来源?

谢谢!

回答

2

这是因为发生了双向绑定,WPF当属性获取一个新的价值,而不是当一个对象由属性更改引用仅检测。

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

当你调用UpdateSource()手动,它迫使的ObservableCollection通过您的转换器并返回到您的数据对象,所以它的工作原理。

得到你想要的行为,最简单的方法是:

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

  2. 在当你构建的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={...}}" 

与转换参数是物业名称

希望这有助于!

+0

谢谢雷!我遵循你所说的话,但我必须说我很惊讶。这不是我如何将这个过程想象为工作。 我很欣赏你对解决方案的建议,但它不适合我的情况。我最终通过观察NotifyCollectionChangedEvents并使用它们来触发BindingExpression.UpdateSource()来解决它。这种方法更适合我的情况。 – 2009-10-31 05:02:42

相关问题