Filtering PropertyChanged events
Recently, while working on a CMS project, I had the need to update a part of the UI if certain values of my business object changed. Basically, the scenario was that if the name of a page changed, the navigational sitemap should also update to reflect the change.
The objects in our business library implement the
INotifyPropertyChanged,
so it's simple enough to subscribe to a PropertyChanged
event. But I
only wanted to determine if a select few of the properties changed so
that I could trigger the display update. One way is to subscribe to the
object's PropertyChanged
event and simply write an if .. else
or
switch
statement based on the property name being passed along.
Another was is to encapsulate the same functionality into a filter object; and that's just what I did by building the PropertyChangeFilter to pass those pesky PropertyChanged events through.
How to use the PropertyChangeFilter
/// instance of a MyObject business object that
/// implements INotifyPropertyChanged
MyObject myObject = new MyObject();
/// create the PropertyChangeFilter to watch myObject
/// for changes in the Name and Title properties
PropertyChangeFilter filter = new PropertyChangeFilter(myObject, "Name", "Title");
// make the necessary changes to the object
myObject.Name = nameTextbox.Text;
myObject.Title = titleTextbox.Text;
/// .. snip other property assignments
myObject.Save();
if (filter.HasChanged)
{
// handle changes to UI, clear a cached item, etc...
}
In the above example, we simply test to see if one of the properties we were listening for has changed. If either the 'Name' or 'Title' changed, the filter's HasChanged property would have been updated to suit.\
Passing events through the filter
The PropertyChangeFilter also implements the INotifyPropertyChanged interface, you can also subscribe to the PropertyChanged events of your object by using the PropertyChangeFilter as a proxy. So instead of getting all the PropertyChanged notifications, you get the ones your interested in.
In this example, which we follow on from our code above, we subscribe to the filters PropertyChanged event, which is raised only when the watched object's Name or Title change.\
filter.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("The '{0}' property has changed!", e.PropertyName);
};
It's worth noting that the sender
argument is the object the event
originated from and not our filter i.e. the sender is our instance of
myObject
.\
Getting a log of the changed properties
One last feature, if you could find a use for it, is to enable the TrackChanges property on the filter like so:
filter.TrackChanges = true;
myObject.Name = "Mouse";
myObject.Lives = 1;
myObject.Name = "Cat";
myObject.Lives = 9;
myObject.Title = "I R Weasel";
myObject.Name = "Amoeba";
string[] changes = filter.Changes.ToArray();
Console.WriteLine( "Log of properties changed: {0}", string.Join( ", ", changes ) );
// prints "Log of properties changed: Name, Name, Title, Name"
That's about all there is to it. It's simple, but yet another little C# Vitamin to help you along your way. You can download the full source code file for the class or the zip which includes a small demo console application.