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!
While adding 'pass-through' properties to your ViewModel is a fine solution, it can quickly become untenable. The standard alternative is to propagate changes as below:
public Address PrimaryAddress {
get => _primaryAddress;
set {
if ( _primaryAddress != value )
{
//Clean-up old event handler:
if(_primaryAddress != null)
_primaryAddress.PropertyChanged -= AddressChanged;
_primaryAddress = value;
if (_primaryAddress != null)
_primaryAddress.PropertyChanged += AddressChanged;
OnPropertyChanged( "PrimaryAddress" );
}
void AddressChanged(object sender, PropertyChangedEventArgs args)
=> OnPropertyChanged("PrimaryAddress");
}
}
Now change notifications are propagated from Address to person.
Edit: Moved handler to c# 7 local function.