Search code examples
c#wpfmvvmbindinginotifypropertychanged

Implementing INotifyPropertyChanged for nested properties


I have a Person class:

public class Person : INotifyPropertyChanged
{
     private string _name;
     public string Name{
     get { return _name; }
     set {
           if ( _name != value ) {
             _name = value;
             OnPropertyChanged( "Name" );
           }
     }

     private Address _primaryAddress;
     public Address PrimaryAddress {
     get { return _primaryAddress; }
     set {
           if ( _primaryAddress != value ) {
             _primaryAddress = value;
             OnPropertyChanged( "PrimaryAddress" );
           }
     }

     //OnPropertyChanged code goes here
}

I have an Address class:

public class Address : INotifyPropertyChanged
{
     private string _streetone;
     public string StreetOne{
     get { return _streetone; }
     set {
           if ( _streetone != value ) {
             _streetone = value;
             OnPropertyChanged( "StreetOne" );
           }
     }

     //Other fields here

     //OnPropertyChanged code goes here
}

I have a ViewModel:

public class MyViewModel
{
   //constructor and other stuff here

     private Person _person;
     public Person Person{
     get { return _person; }
     set {
           if ( _person != value ) {
             _person = value;
             OnPropertyChanged( "Person" );
           }
     }

}

I have a View which has the following lines:

<TextBox  Text="{Binding Person.Name, Mode=TwoWay,   
    UpdateSourceTrigger=PropertyChanged />

<TextBox  Text="{Binding Person.Address.StreetOne, Mode=TwoWay,   
    UpdateSourceTrigger=PropertyChanged />

Both values show up in the text box ok when the view loads.

Changes to the first text box will fire OnPropertyChanged( "Person" ) in MyViewModel. Great.

Changes to the second text box ("Person.Address.StreetOne") does NOT fire OnPropertyChanged( "Person" ) inside MyViewModel. Meaning it doesn't call the Person object's SET method. Not great. Interestingly the SET method of StreetOne inside the Address class is called.

How do I get the SET method of the Person object inside the ViewModel to be called when Person.Address.StreetOne is changed???

Do I need to flatten my data so SteetOne is inside Person and not Address??

Thanks!


Solution

  • if you want the viewmodel SET to be called you could create a street property

    public class MyViewModel
    {
      //constructor and other stuff here
      public string Street{
        get { return this.Person.PrimaryAddress.StreetOne; }
        set {
           if ( this.Person.PrimaryAddress.StreetOne!= value ) {
             this.Person.PrimaryAddress.StreetOne = value;
             OnPropertyChanged( "Street" );
           }
       }
    
     }
    

    xaml

    <TextBox  Text="{Binding Street, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged />
    

    but this solution has its drawbacks. i go with Reeds answer in my projects