How to implement INotifyPropertyChanged without strings and support Asynchronous Notification


In this post I want to show you an alternative way of implementing INotifyPropertyChanged with a nice, string-less way of raising the PropertyChanged event.

It implements usual INotifyPropertyChanged infrastructure and allows you to have strongly-typed property notifications (instead of mangling with strings). Also because PropertyChanged event can be raised from asynchronous code (ie raised from different thread than main) it needs to be dispatched to the main thread which is done by using simple utility class Call and it’s OnUIThread() routine.

For example in your ViewModel you want to create a property call “MyProp”, and on line 12 instead of using a literal string you now use a strongly type property with intellisense support from Visual Studio:

    public class MyViewModel : ViewModelBase
    {
        private string myProp;
        public string MyProp
        {
            get { return myProp; }
            set
            {
                if (this.myProp != value)
                {
                    myProp = value;
                    NotifyOfPropertyChange(() => MyProp);
                }
            }
        }
    }

First, you create a base class ViewModelBase.cs like this:

public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        public void NotifyOfPropertyChange(string propertyName)
        {
            Call.OnUIThread(() => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)));
        }

        public void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
        {
            var lambda = (LambdaExpression)property;

            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression)lambda.Body;
                memberExpression = (MemberExpression)unaryExpression.Operand;
            }
            else
            {
                memberExpression = (MemberExpression)lambda.Body;
            }

            NotifyOfPropertyChange(memberExpression.Member.Name);
        }
    }

plus a helper class Call.cs that:

    public static class Call
    {
        public static void OnUIThread(Action action)
        {
            Dispatcher dispatcher = Deployment.Current.Dispatcher;

            if (dispatcher.CheckAccess())
            {
                action();
                return;
            }

            dispatcher.BeginInvoke(action);
        }
    }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s