I have a situation I’m not sure how to debug. I’m hoping someone can suggest why it might not be working and point me in the right direction.
I have a TIFF image from a database which is exposed as a property of type System.Data.Linq.Binary. I want to display the individual frames from that TIFF image in an ItemsControl so I’ve written a converter that takes the Binary datatype and returns an ObservableCollection of BitmapFrames. I’m binding ItemsControl.ItemsSource to the Binary property using the converter along with "Mode=TwoWay" and "UpdateSourceTrigger=PropertyChanged".
The display of the images is working fine. The problem is that if I add a frame to the collection the display updates, but that change is not transferred back to the Binary property in the source object. The ConvertBack() method in my converter is never called (indicating to me that the binding is never even trying to update the source). If I manually make a call to BindingExpression.UpdateSource() as if it were set for "UpdateSourceTrigger=Explicit" the Binary property does update correctly.
So if a binding is set for "Mode=TwoWay" and "UpdateSourceTrigger=PropertyChanged" and the object implements INotifyPropertyChanged (which ObserverableCollection does), why doesn’t the binding actually try to update the source?
Thanks!
This is happening because for TwoWay bindings, WPF only detects when the property gets a new value, not when an object referenced by the property changes.
In your case your property contains the ObservableCollection created by your converter. Although the contents of the ObservableCollection has been modified, and it fires INotifyPropertyChanged, the bound property itself has not changed: It still refrences the same ObservableCollection as before. Because of this, WPF DataBinding is not triggered and your source is not updated.
When you call UpdateSource() manually, it forces the ObservableCollection to be passed through your converter and back to your data object, so it works.
The easiest way to get the behavior you desire is:
Instead of binding to the data field, bind to the data object, and extract the desired field in the converter (if you want to make a generic converter that can access any field, pass the field as a parameter).
In the converter when you construct the ObservableCollection, add a CollectionChanged event that updates the original object whenever it fires.
Here is the general idea in code:
In this case your binding would change from
to
with the converter parameter being the property name
Hope this helps!