Welcome to EMC Consulting Blogs Sign in | Join | Help

Merrick Chaffer's Blog

A simple implementation of INotifyPropertyChanged

There are many variations out there on this theme of how to keep your code strongly typed whilst implementing the PropertyChanged event of the System.ComponentModel.INotifyPropertyChanged interface. This one I think is fairly simple to follow using Lambda expression member bodies to extract the name of a property instead of hard coding the string of the property name which is prone to future refactoring errors at runtime, when a dev updates the property name.

Usage is as simple as the following...

    using System.ComponentModel.Composition;

    [Export]
    public class MainViewViewModel : BaseViewModel
    {
        private int alarmCount;

        public int AlarmCount
        {
            get
            {
                return this.alarmCount;
            }

            set
            {
                this.SetPropertyValue(ref this.alarmCount, value, () => this.AlarmCount);
            }
        }
    }

Implementation is as follows...

    using System;
    using System.ComponentModel;
    using System.Linq.Expressions;

    public abstract class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void SetPropertyValue<T>(ref T oldValue, T newValue, Expression<Func<T>> expression)
        {
            if ((Equals(oldValue, default(T)) && Equals(newValue, default(T)))
                || Equals(oldValue, newValue))
            {
                return;
            }

            var propertyName = GetPropertyName(expression);

            oldValue = newValue;

            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Returns the string name of a property.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        /// <returns>The name of the property as a <see cref="System.String"/></returns>
        private static string GetPropertyName<T>(Expression<Func<T>> expression)
        {
            if (expression.NodeType != ExpressionType.Lambda)
            {
                throw new ArgumentException("Value must be a lamda expression", "expression");
            }

            if (!(expression.Body is MemberExpression) )
            {
                throw new ArgumentException("The body of the expression must be a memberref", "expression");
            }

            var body = (MemberExpression)expression.Body;

            return body.Member.Name;
        }
    }

Update: 10:47 25/01/2010: Have created resharper live template for creating a property like the one in the usage example.

private $TYPE$ $propertyName$;
public $TYPE$ $PropertyName$
{
    get
    {
        return this.$propertyName$;
    }

    set
    {
        this.SetPropertyValue(ref this.$propertyName$, value, () => this.$PropertyName$);
    }
}
$END$
Published 22 January 2010 15:39 by merrick.chaffer

Comments

No Comments
Anonymous comments are disabled

This Blog

Syndication

News

Powered by Community Server (Personal Edition), by Telligent Systems