The longer I’ve worked with WPF, the more implementations I have seen of the INotifyPropertyChanged interface. It’s everywhere. I have seen dozens upon dozens of classes all implement the interface separately, even though most of those classes descend directly from Object. This blog post examines the virtues of creating a base class which implements that interface, and deriving as many classes as possible from it.
Consolidating your implementation of INotifyPropertyChanged into a base class has several benefits.
- You do not have to implement the same interface many times, which reduces the possibility of boredom (and programming errors…).
- You can easily use cached instances of PropertyChangedEventArgs, to avoid fragmenting the managed heap with semantically identical instances.
- You can easily use some reflection magic to verify that the property which allegedly changed actually exists (this is useful for debugging purposes, and is automatically turned off in Release builds).
- You can override a method to execute logic which must run after a property is set.
I created an abstract class called BindableObject which implements INotifyPropertyChanged and provides all the goodies promised above. At the bottom of this post you can download the source code. Until then, let’s take a look at how it’s implemented.
Here’s the class from a high-level view:
As you can see above, classes which descend from BindableObject can call the RaisePropertyChanged method when one of their public properties is set to a new value. That will cause the INotifyPropertyChanged.PropertyChanged event to be raised so that the data binding system is alerted of the new value. If a child class wants to perform some processing after a property is set, it can override the AfterPropertyChanged method.
I made the class serializable in case you need it to be. The demo project does not make use of that aspect of the class. Now let’s take a look at the class’s protected members:
Now we’ll inspect the public members of BindableObject:
The main point of interest here is the GetPropertyChangedEventArgs method. It maintains a cache of PropertyChangedEventArgs instances, so that only one instance will exist for each property name passed through this class. This caching can dramatically reduce the managed heap fragmentation caused by a property being set many times in a short period of time. The reason I made GetPropertyChangedEventArgs public is so that any class can take advantage of its caching mechanism, even if the class does not descend from BindableObject.
In case you’re curious, here is how the property name is verified:
If a class which descends from BindableObject passes an invalid property name into the RaisePropertyChanged method, when the property is set this helpful assertion dialog will open:
Download the demo project here: BindableObject (demo project) Be sure to change the file extension from .DOC to .ZIP and then decompress it.