I’m looking for a clean and elegant solution to handle the INotifyPropertyChanged event of nested (child) objects. Example code:
public class Person : INotifyPropertyChanged {
private string _firstName;
private int _age;
private Person _bestFriend;
public string FirstName {
get { return _firstName; }
set {
// Short implementation for simplicity reasons
_firstName = value;
RaisePropertyChanged("FirstName");
}
}
public int Age {
get { return _age; }
set {
// Short implementation for simplicity reasons
_age = value;
RaisePropertyChanged("Age");
}
}
public Person BestFriend {
get { return _bestFriend; }
set {
// - Unsubscribe from _bestFriend's INotifyPropertyChanged Event
// if not null
_bestFriend = value;
RaisePropertyChanged("BestFriend");
// - Subscribe to _bestFriend's INotifyPropertyChanged Event if not null
// - When _bestFriend's INotifyPropertyChanged Event is fired, i'd like
// to have the RaisePropertyChanged("BestFriend") method invoked
// - Also, I guess some kind of *weak* event handler is required
// if a Person instance i beeing destroyed
}
}
// **INotifyPropertyChanged implementation**
// Implementation of RaisePropertyChanged method
}
Focus on the BestFriend Property and it’s value setter. Now I know that I could do this manually, implementing all steps described in the comments. But this is going to be a lot of code, especially when I’m planning to have many child properties implementing INotifyPropertyChanged like this. Of course they are not going to be always of same Type, the only thing they have in common is the INotifyPropertyChanged interface.
The reason is, that in my real scenario, I have a complex “Item” (in cart) object which has nested object properties over several layers (Item is having a “License” object, which can itself have child objects again) and I need to get notified about any single change of the “Item” to be able to recalculate the price.
Do you some good tips or even some
implementation to help me to solve
this?
Unfortunately, I’m not able/allowed to use post-build steps like PostSharp to accomplish my goal.
since I wasn’t able to find a ready-to-use solution, I’ve done a custom implementation based on Pieters (and Marks) suggestions (thanks!).
Using the classes, you will be notified about any change in a deep object tree, this works for any
INotifyPropertyChangedimplementing Types andINotifyCollectionChanged* implementing collections (Obviously, I’m using theObservableCollectionfor that).I hope this turned out to be a quite clean and elegant solution, it’s not fully tested though and there is room for enhancements. It’s pretty easy to use, just create an instance of
ChangeListenerusing it’s staticCreatemethod and passing yourINotifyPropertyChanged:the
PropertyChangedEventArgsprovide aPropertyNamewhich will be always the full “path” of your Objects. For example, if you change your Persons’s “BestFriend” Name, thePropertyNamewill be “BestFriend.Name”, if theBestFriendhas a collection of Children and you change it’s Age, the value will be “BestFriend.Children[].Age” and so on. Don’t forget toDisposewhen your object is destroyed, then it will (hopefully) completely unsubscribe from all event listeners.It compiles in .NET (Tested in 4) and Silverlight (Tested in 4). Because the code in seperated in three classes, I’ve posted the code to gist 705450 where you can grab it all: https://gist.github.com/705450 **
*) One reason that the code is working is that the
ObservableCollectionalso implementsINotifyPropertyChanged, else it wouldn’t work as desired, this is a known caveat**) Use for free, released under MIT License