C# – WPF Databinding Magic


I have ObservableCollection<Foo> that is bound to an ItemsControl (basically displaying a list).

Foo mostly looks like this (there are other members but it doesn't implement any interfaces or events):

class Foo
  public string Name { get; set; }

When the user clicks on an item I open a dialog where the user can edit Foo's properties (bound to a small viewmodel with a Foo property for the selected item), the Xaml looks like this:

<TextBox Text="{Binding Foo.Name,Mode=TwoWay}"
    Grid.Column="1" Grid.Row="0" Margin="2" />

The really strange thing is, when the user edits the name, the value in the list changes! (not while typing but after the focus leaves the field)

How does it do that? I haven't implemented the INotifyPropertyChanged interface on the Foo object!

So far I checked that it doesn't just refresh the whole list – only the selected item. But I don't know where I could set a breakpoint to check who's calling.

Update: thanks to casperOne for the link to the solution! I'll add a summary here in case it goes 404:

[..] actually you are encountering a another hidden aspect of WPF, that's it WPF's data binding engine will data bind to PropertyDescriptor instance which wraps the source property if the source object is a plain CLR object and doesn't implement INotifyPropertyChanged interface. And the data binding engine will try to subscribe to the property changed event through PropertyDescriptor.AddValueChanged() method. And when the target data bound element change the property values, data binding engine will call PropertyDescriptor.SetValue() method to transfer the changed value back to the source property, and it will simultaneously raise ValueChanged event to notify other subscribers (in this instance, the other subscribers will be the TextBlocks within the ListBox.

And if you are implementing INotifyPropertyChanged, you are fully responsible to implement the change notification in every setter of the properties which needs to be data bound to the UI. Otherwise, the change will be not synchronized as you'd expect.

Best Solution

This is a total guess, but I'm thinking that because you have two-way binding enabled, WPF is now aware of when it makes changes, and will update other items it knows is bound to the same instance.

So because you have changed the value of the Name property through the textbox, and WPF knows when you have changed that value, it does its best to update whatever else it knows is bound to it.