Wpf DataBinding And INotifyPropertyChanged

In WPF, data binding between a binding target which is normally a ui control property (DepdencyProperty) and  a binding source which is normally the view model property can be two way.  There is hardly any issues of binding from target to source, that is the changes on UI are quite reliably pushed back to source the view model, but to get UI updates every time model changes is not very obvious.

First for most , the model must implement INotifyPropertyChanged, and OnPropertyChanged event of that property  must be raised.

So even though you set the binding mode as TwoWay, if the model property change event is not raised, there is no way, UI will get the notices of change. For UI to respond model change, model property must raise OnPropertyChanged.

Here is an example of my view model that implements INotifyPropertyChanged

</pre>
public class DummyViewModel :INotifyPropertyChanged

{

public DummyViewModel()

{

}

public string MyText {get;set;}

private string _anotherText;

public string AnotherText

{

get

{

return _anotherText;

}

set

{

_anotherText = value;

OnPropertyChanged("AnotherText");

OnPropertyChanged("MyText");

}

}

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

handler(this, new PropertyChangedEventArgs(propertyName));

}

}
<pre>

There is nothing unusual except there are two OnPropertyChanged events raised in AnotherText setter. The reason we raise MyText property change in AnotherText setter is MyText itself does not implement  INotifyPropertyChanged (to save a few lines of code?).

The question is  MyText bound UI is going to be updated as well?

The answer is it depends, there is a timing issue here, if you changed MyText before AnotherText, the both UI controls  will be updated,  but if MyText is changed after AnotherText, the event is already raised, so the MyText control will not be updated.

The lesson is raising on property changed on behalf of another property is not safe, you have to make sure that the model changes to another property are made before the event raiser.

According to the MSDN document if you pass a null or string.Empty as property name for OnPropertyChanged(string.Empty), it will update all properties of view model, again UI can only catch changes up to the point this event is raised. So if you choose this way, make sure

the implementing property is the last property to update.

</pre>
viewModel.MyText = "MyText";

viewModel.AnotherText = "AnotherText";
<pre>

Not in  this order

</pre>
viewModel.AnotherText = "AnotherText";

viewModel.MyText = "MyText";
<pre>

There is another interesting scenario, that the property is a custom object, it has its own properties

Like

</pre>
public class DummyViewModel :INotifyPropertyChanged

{

public DummyViewModel()

{

_myChild = new Child();

}

private Child _myChild;

public Child MyChild

{

get

{

return _myChild;

}

set

{

_myChild = value;

OnPropertyChanged("MyChild");

}

}

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

handler(this, new PropertyChangedEventArgs(propertyName));

}

}

public class Child

{

public string MyText { get; set; }

public string AnotherText { get; set; }

}
<pre>

And binding is like


<TextBox Text="{Binding Path=MyChild.MyText, Mode=TwoWay}" Width="200"></TextBox>

<TextBox Text="{Binding Path=MyChild.AnotherText, Mode=TwoWay}" Width="200"/>

In this case, if you update model like this

</pre>
var child = new Child

{

AnotherText = "MyChildAnotherText",

MyText = "MyChildMyText"

};

viewModel.MyChild = child;
<pre>

The property change event will be raised, and all its properties of MyChild will be updated in UI even though they do not implement OnPropertyChanged themselves

But if you update child properties in this way

</pre>
viewModel.MyChild.AnotherText = "MyChildAnotherText";

viewModel.MyChild.MyText = "MyChildMyText";
<pre>

There will be no updates in UI, as no property changed event is raised.

You do not have to implement on property changes of every property, especially they are properties of another parent object. But it has to be done in a right way.

Summary:

To update UI with model change, model must implement INotifyPropertyChanged, not all properties need to raise OnPropertyChanged event, raise OnPropertyChanged event with null or string.empty as property name will cause all binding properties update in UI by the time of that point. When property is complex type, it is child properties will be updated when complex type property change is notified.

Tags:

This entry was posted on Thursday, March 6th, 2014 at 8:58 pm and is filed under ASP.NET. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply

*