In the next article in this series, I introduce the idea of Property Change Behaviors. This concept is used to provide a means of easily attaching useful features to data objects. Any number of features can be added without requiring a complex inheritance structures or keeping you from configuring the features on a per-property or per-instance basis.
This article is part of a series about useful MVVM friendly features for your data objects and favoring composition over inheritance. You can read the other parts:
Can we all agree to call Silverlight/WPF development “XamlWorld” ?
Introducing Property Change Behaviors
Recall that we opened the first article with a list of actions we might want to take when a property on a XAMLWorld data object changes:
- Firing change notification
- Handling property-level validation
- Tracking when an object has changed (dirty/change tracking)
- Update dependent or calculated properties
- Providing Undo support
It would be ideal if we could provide a mechanism to do all of these things, and whatever else we think of in the future, in a generic fashion. Since XAML technologies provide fantastic data binding support centered around the notion of CLR Properties, connecting our behaviors to properties is a very good approach. If you want to use anything that’s built into XamlWorld, you need to make peace with the notion that The Property is the coin of the realm.
We can think of Property Changed Behaviors as a sort of “visitor” or “Chain of Responsibility”. Here is the interface for Property Change Behaviors:
public interface IPropertyChangedBehavior
{
/// <summary>
/// Do something useful when a property changes
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="owningInstance">Object instance whose property has changed</param>
/// <param name="oldVal">current property value</param>
/// <param name="newVal">new property value</param>
/// <param name="propertyName"></param>
/// <returns>Returns true of more behaviors can keep processing</returns>
bool PropertyChanged<T>(object owningInstance, T oldVal, T newVal, string propertyName);
}
There are more complex scenarios for IPropertyChangedBehavior, but for this series of articles we’ll stick with the first draft. This interface allows us to do interesting things when Property values change.
Remember what our BindableType property setter looked like previously? Recall that we did this to avoid re-creating the basic INotifyPropertyChanged implementation over and over:
protected void OnPropertyChanged(string propName)
{
if (null != PropertyChanged && !SuspendChangeNotification)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
In order to move forward I’ve changed the semantics somewhat. The code snippet for setting properties in this style is provided at the end of this article. Keeping with the Metro BBQ example from the previous article, here’s what the properties look like on my BBQGrill class.
Materials _KettleMaterial;
public Materials KettleMaterial
{
get { return _KettleMaterial; }
set { Set<Materials>(ref _KettleMaterial, value, "KettleMaterial"); }
}
This allows me to use semantics like the following on the BindableType base class. Yes, we’re still extending BindableType for now, one step at a time. We will eventually refactor to avoid the need to extend BindableType.
protected void Set<T>(ref T local, T newVal, string name)
{
T localCopy = local;
local = newVal;
if (null != _changeBehaviors)
{
foreach (var behavior in _changeBehaviors)
{
bool @continue = behavior.PropertyChanged<T>(this, localCopy, newVal, name);
if (!@continue) { break; }
}
}
else//no behaviors, just carry on with the old way
{
OnPropertyChanged(name);
}
}
Now things are starting to get interesting. BindableType has an instance variable to contain the IPropertyChangedBehaviors we want to use.
protected IEnumerable<IPropertyChangedBehavior> _changeBehaviors;
Each object now has a configurable list of interesting actions that we can go through any time a property value changes. Based on the fact that we’d like to enable Binding updates, the choice for the first IPropertyChangedBehavior implementation is obvious:
public class NotifyPropertyBehavior : IPropertyChangedBehavior
{
public NotifyPropertyBehavior(INotifyPropertyChanged target, Action<string> changedCallback)
{
Requires.NotNull(target, "target cannot be null");
Requires.NotNull(changedCallback, "changedCallback cannot be null");
Target = target;
ChangeCallback = changedCallback;
}
public INotifyPropertyChanged Target { get; set; }
/// <summary>
/// Needed since only the owning instance can fire the event
/// </summary>
public Action<string> ChangeCallback { get; set; }
/// <summary>
/// Fire change notification only if the new value != old
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="owningInstance"></param>
/// <param name="oldVal"></param>
/// <param name="newVal"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public bool PropertyChanged<T>(object owningInstance, T oldVal, T newVal, string propertyName)
{
if (!Object.Equals(oldVal, newVal))
{
ChangeCallback(propertyName);
return true;
}
else
{
return false;
}
}
}
… and in the constructor of BindableType, we create the following defaults used in the Setter, above:
_changeBehaviors = new List<IPropertyChangedBehavior>
{ new NotifyPropertyBehavior(this, s=> OnPropertyChanged(s) ) };
Now, we are in a situation where our data objects can have any number of IPropertyChangedBehaviors attached. For now, the NotifyPropertyBehavior has merely replaced how we fire change notification, but the behaviors shown in the following articles will implement much more interesting functionality.

Conclusion
So, we’ve created some basic functionality for iterating through an ordered list of interesting actions whenever a property value changes. Based on the logic inside BindableType, if the property values are equal we would stop processing subsequent Property Change Behaviors for this instance by returning false from NotifyPropertyBehavior.
In the next article we’ll start adding more useful and interesting features using the IPropertyChangedBehavior approach.
Download the bprop code snippet.