Generic Notify Property Change Controller
Posted by Dan Rigsby on March 14th, 2008
This is another example of a class you could put into a common library. Suppose I want to create a class that fires an event every time the value of a property changes. I could implement such a class like this:
public class MyClass : INotifyPropertyChanged { private string m_Text; public string Text { get { return m_Text; } set { if (m_Text != value) { m_Text = value; OnPropertyChanged("Text"); } } } protected virtual void OnPropertyChanged( string propertyName) { PropertyChangedEventHandler handler = m_PropertyChanged; if (handler != null) { m_PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #region INotifyPropertyChanged Members private event PropertyChangedEventHandler m_PropertyChanged; public event PropertyChangedEventHandler PropertyChanged { add { m_PropertyChanged += value; } remove { m_PropertyChanged -= value; } } #endregion INotifyPropertyChanged Members }
public class MyClass : INotifyPropertyChanged { private PropertyController m_PropertyController private string m_Text; public string Text { get { return m_Text; } set { m_PropertyController.ChangeProperty("Text", value); } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged { add { m_PropertyController.PropertyChanged += value; } remove { m_PropertyController.PropertyChanged -= value; } } #endregion INotifyPropertyChanged Members }
That is significantly less code and much cleaner. Just, imagine if I had a class library with 30 classes.
You could also do this:
set { m_PropertyController.ChangeProperty("Text", value);
instead of:
set { m_PropertyController.ChangeProperty(value);
The cost of doing this is that the PropertyController has to look at the stack trace, but depending on what you are doing, this may be worth the cost.
The ChangeProperty method returns a boolean to indicate whether or not the value was changed. So inside your property code you could react depending on the result.
Here is the complete PropertyController class. Feel free to use it, modify it, ignore it, etc. You could even use this class and not even expose the PropertyChanged event, if you don’t need it.
public class PropertyController : INotifyPropertyChanged, IDisposable { private Dictionary<string, PropertyInfo> m_Properties = new Dictionary<string, PropertyInfo>(); public PropertyController() { } #region INotifyPropertyChanged Members private event PropertyChangedEventHandler m_PropertyChanged; public event PropertyChangedEventHandler PropertyChanged { add { m_PropertyChanged += value; } remove { m_PropertyChanged -= value; } } #endregion INotifyPropertyChanged Members protected PropertyInfo GetProperty(string propertyName) { if (!m_Properties.ContainsKey(propertyName)) { m_Properties.Add(propertyName, this.GetType().GetProperty(propertyName)); } return m_Properties[propertyName]; } public virtual bool ChangeProperty(object newValue) { return ChangeProperty(new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().Name, newValue); } public virtual bool ChangeProperty(string propertyName, object newValue) { System.Reflection.PropertyInfo property = GetProperty(propertyName); if (property.GetValue(this, null) != newValue) { property.SetValue(this, newValue, null); OnPropertyChanged(propertyName); return true; } return false; } public virtual void OnPropertyChanged( string propertyName) { PropertyChangedEventHandler handler = m_PropertyChanged; if (handler != null) { m_PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #region IDisposable Members public void Dispose() { m_PropertyChanged = null; } #endregion IDisposable Members }











March 18th, 2008 at 3:10 pm
I think you need to pass newValue parameter in a call to ChangeProperty method in ChangeProperty(object newValue)overload. Otherwise, ChangeProperty will recursively call itself thus leading to an eventual stack overflow.
March 18th, 2008 at 4:42 pm
Yup, “duh” on my behalf. I added in that overridden method at the last minute. Updated and thanks!