2

I have the following method:

void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "InitializeFailureMessage":
            if (Vm.InitializeFailureMessage != null)
                ShowInitializeFailure(Vm.InitializeFailureMessage);
            break;
    }
}

Just now, the method had a bug: the property used to be called InitializeFailureErrorMessage, and when it was renamed, no one updated the string in this handler.

Is there a better, less error-prone way to subscribe to the PropertyChanged event? When firing the event we can now use [CallerMemberName]. Is there a similar trick when implementing the handler?

Oliver
  • 11,297
  • 18
  • 71
  • 121

2 Answers2

2

Quick idea using extension method, expression and delegates:

public static class Extension
{
    public static void RegisterNotify<T>(this T obj, Expression<Func<T, object>> propExpr, Action action) where T : INotifyPropertyChanged
    {
        string name = GetPropertyName(propExpr);
        obj.PropertyChanged += (s, e) => { if (e.PropertyName == name) action() };
    }
}

And it is called like:

    Notifier obj = new Notifier(); // implements INotifyPropertyChanged
    obj.RegisterNotify(x => x.Property, () => { /* do something when Property changes */ });
    obj.RegisterNotify(x => x.Property2, () => { /* do something else when Property2 changes */ });
Euphoric
  • 12,645
  • 1
  • 30
  • 44
  • What if we have two properties? That would subscribe the event twice isn't it? – Sriram Sakthivel Nov 26 '13 at 13:40
  • @SriramSakthivel Yes, is that a problem? I don't think it will have any big impact on performance unless you register many properties and call them quite often. – Euphoric Nov 26 '13 at 13:41
  • yes, **definitely** a problem. All action will be executed several times as you execute. consider `{ account.Balance -=10 ;}` as a action. This will execute as many times you subscribed which is not intended behavior. sidenote:this can be fixed easily though. – Sriram Sakthivel Nov 26 '13 at 13:46
  • @SriramSakthivel No... each registration is separate. So your action will execute exactly once if you registered it only once. Unrelated to other registrations. – Euphoric Nov 26 '13 at 13:48
  • Could you pls provide complete sample? with two properties of `Notifier` subscribed. Let's say `Property1` and `Property2`. Am not certain about what you think. may be this is a *communication gap*? – Sriram Sakthivel Nov 26 '13 at 13:51
  • +1.. This looks good.. :) Again, this approach lacks un-subscription of event. Once subscribed you cant remove it :) – Sriram Sakthivel Nov 26 '13 at 14:02
1

Use this utility method to get the property name using Expressions.

Consider this is your class which fires the event, introduce a static readonly string field which tells the string representation of property. Then use that static field to check which was the property changed.

class MyClass
{
    public static readonly string InitializeFailureMessageProperty = GetPropertyName(() => x.InitializeFailureMessageProperty);//x can be a dummy instance.
}

void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == MyClass.InitializeFailureMessageProperty)
    {
         if (Vm.InitializeFailureMessage != null)
             ShowInitializeFailure(Vm.InitializeFailureMessage);
    }
}
Community
  • 1
  • 1
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • Nice suggestions, thanks. the trick with the static readonly string could be useful sometimes, as there is some performance overhead with Expressions. – Oliver Nov 26 '13 at 13:39
  • @Oliver Yes, That's why I choose `static readonly` which is going to happen at most once in a appdomain. :) – Sriram Sakthivel Nov 26 '13 at 13:42
  • @Oliver Are you really going to register so much and so often that expression overhead is such concern? – Euphoric Nov 26 '13 at 13:42