views:

453

answers:

4

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.

A: 

It uses reflection to set the value of that property. INotifyPropertyChanged is only needed if the TextBox needs to be informed of a change in the Name property of the Foo class.

Lars Truijens
Yes, but how does the list know about the change without INotifyPropertyChanged?
chris
+4  A: 

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.

casperOne
That's an interesting idea! Do you know how I could confirm that?
chris
@chris: If I knew, I wouldn't have said "This is a total guess". If I find out though, I'll post back.
casperOne
@chris: Check out this thread on MSDN forums, which is answered by someone in MS: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/9365bb6a-b411-4967-9a03-ae2a810fb215/
casperOne
Wow, thank you for the explanation and the quick reply!
chris
A: 

Because they're databound to the same object. If you change the binding to

{Binding Foo.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}

then they'll be in synch when the user types in the textbox.

amaca
A: 

The most useful answer is provided in the edit to the question and also in this link provided by @casperone.

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/9365bb6a-b411-4967-9a03-ae2a810fb215/

Another discussion is here : http://forums.msdn.microsoft.com/en/wpf/thread/8e4f9b09-fd14-4be7-9d4b-f6038cd61e6d

Simon_Weaver