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$