There is no Single implementation of Property Changed that can handle every way that people want to use it. best bet is to generate a helper class to do the work for you here is an example of one i use
/// <summary> /// Helper Class that automates most of the actions required to implement INotifyPropertyChanged /// </summary> public static class HPropertyChanged { private static Dictionary<string, PropertyChangedEventArgs> argslookup = new Dictionary<string, PropertyChangedEventArgs>(); public static string ThisPropertyName([CallerMemberName]string name = "") { return name; } public static string GetPropertyName<T>(Expression<Func<T>> exp) { string rtn = ""; MemberExpression mex = exp.Body as MemberExpression; if(mex!=null) rtn = mex.Member.Name; return rtn; } public static void SetValue<T>(ref T target, T newVal, object sender, PropertyChangedEventHandler handler, params string[] changed) { if (!target.Equals(newVal)) { target = newVal; PropertyChanged(sender, handler, changed); } } public static void SetValue<T>(ref T target, T newVal, Action<PropertyChangedEventArgs> handler, params string[] changed) { if (!target.Equals(newVal)) { target = newVal; foreach (var item in changed) { handler(GetArg(item)); } } } public static void PropertyChanged(object sender,PropertyChangedEventHandler handler,params string[] changed) { if (handler!=null) { foreach (var prop in changed) { handler(sender, GetArg(prop)); } } } public static PropertyChangedEventArgs GetArg(string name) { if (!argslookup.ContainsKey(name)) argslookup.Add(name, new PropertyChangedEventArgs(name)); return argslookup[name]; } }
edit: it was suggested that i shift from a helper class to a value wrapper and i've since been using this one and i find it works quite well
public class NotifyValue<T> { public static implicit operator T(NotifyValue<T> item) { return item.Value; } public NotifyValue(object parent, T value = default(T), PropertyChangingEventHandler changing = null, PropertyChangedEventHandler changed = null, params object[] dependenies) { _parent = parent; _propertyChanged = changed; _propertyChanging = changing; if (_propertyChanged != null) { _propertyChangedArg = dependenies.OfType<PropertyChangedEventArgs>() .Union( from d in dependenies.OfType<string>() select new PropertyChangedEventArgs(d) ); } if (_propertyChanging != null) { _propertyChangingArg = dependenies.OfType<PropertyChangingEventArgs>() .Union( from d in dependenies.OfType<string>() select new PropertyChangingEventArgs(d) ); } _PostChangeActions = dependenies.OfType<Action>(); } private T _Value; public T Value { get { return _Value; } set { SetValue(value); } } public bool SetValue(T value) { if (!EqualityComparer<T>.Default.Equals(_Value, value)) { OnPropertyChnaging(); _Value = value; OnPropertyChnaged(); foreach (var action in _PostChangeActions) { action(); } return true; } else return false; } private void OnPropertyChnaged() { var handler = _propertyChanged; if (handler != null) { foreach (var arg in _propertyChangedArg) { handler(_parent, arg); } } } private void OnPropertyChnaging() { var handler = _propertyChanging; if(handler!=null) { foreach (var arg in _propertyChangingArg) { handler(_parent, arg); } } } private object _parent; private PropertyChangedEventHandler _propertyChanged; private PropertyChangingEventHandler _propertyChanging; private IEnumerable<PropertyChangedEventArgs> _propertyChangedArg; private IEnumerable<PropertyChangingEventArgs> _propertyChangingArg; private IEnumerable<Action> _PostChangeActions; }
example of use
private NotifyValue<int> _val; public const string ValueProperty = "Value"; public int Value { get { return _val.Value; } set { _val.Value = value; } }
then in constructor you do
_val = new NotifyValue<int>(this,0,PropertyChanged,PropertyChanging,ValueProperty );
INotifyPropertyChangedand changes detection: codeproject.com/KB/cs/INotifyPropertyChanged.aspx