Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Every time I go to write an MVVM application (say every 4-6 months) I rewrite my ViewModelBase class. This is for a range of reasons but let's say either I don't have access to prior code, the previous code was built for a client and isn't my code, or I'm working on someone else's machine and still don't have the code.

So I rewrite the basic INotifyPropertyChanged implementation, and I think it's a little different each time. Here's what I've come up with today:

public class ViewModelBase : INotifyPropertyChanged
{
    protected void OnPropertyChanged<T>(Expression<Func<T>> expression)
    {
        var property = (MemberExpression)expression.Body;
        this.OnPropertyChanged(property.Member.Name);
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

I would like to get a nice implementation that is simple and small, and any improvements to this (what other functionality is required in a ViewModelBase?) would be great.

share|improve this question
    
I've never considered doing this. I'm interested to see what context would this be useful when using the view model on the view? Do you have any example code of it's usage? – dreza Jul 19 '12 at 10:19
1  
@dreza Which part in particular? Implementing the INotifiyPropertyChanged interface is basic functionality that a ViewModel needs to provide, and I'm just sharing that across my ViewModels... – Kirk Broadhurst Jul 24 '12 at 2:06
    
Yeah, I understand the functionality. I was interested to see in what context it was used as it it's my understanding that every view model does not need to provide the functionality. However I've done a bit of googling about it anyway cheers. – dreza Jul 24 '12 at 20:47
up vote 7 down vote accepted

I've used the below for a while:

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

    protected void RaisePropertyChanged(string propertyName)
    {
        var propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected bool SetProperty<T>(ref T backingField, T Value, Expression<Func<T>> propertyExpression)
    {
        var changed = !EqualityComparer<T>.Default.Equals(backingField, Value);

        if (changed)
        {
            backingField = Value;
            this.RaisePropertyChanged(ExtractPropertyName(propertyExpression));
        }

        return changed;
    }

    private static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
        var memberExp = propertyExpression.Body as MemberExpression;

        if (memberExp == null)
        {
            throw new ArgumentException("Expression must be a MemberExpression.", "propertyExpression");
        }

        return memberExp.Member.Name;
    }
}

I can write my properties like this:

    private int id;

    public int Id
    {
        get
        {
            return this.id;
        }

        set
        {
            this.SetProperty(ref this.id, value, () => this.Id);
        }
    }
share|improve this answer

Specifically related to NotifyPropertyChanged I've found VerifyPropertyName to be useful.

From Josh Smith's site: A base class which implements INotifyPropertyChanged

[Conditional("DEBUG"), DebuggerStepThrough()]
public void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,  
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)(propertyName) == null) {
    string msg = "Invalid property name: " + propertyName;

    if (this.ThrowOnInvalidPropertyName) {
        throw new Exception(msg);
    } else {
        Debug.Fail(msg);
    }
}
}
share|improve this answer

This is many years later, but anyone stumbling upon this now should be aware of MVVM Light and PropertyChanged.Fody

Both are on nuget.org

share|improve this answer
protected void OnPropertyChanged<T>(Expression<Func<T>> expression)
{
    var property = (MemberExpression)expression.Body;
    this.OnPropertyChanged(property.Member.Name);
}
  • Expression<Func<T>> is a pretty expensive allocation, usually not a problem but good to know. Used BenchmarkDotNet and ran a benchmark for fun, here are the results:
                      Method |        Median |     StdDev | Scaled |
    ------------------------ |-------------- |----------- |------- |
     SetWithCallerMemberName |     2.5169 ns |  0.3584 ns |   1.00 |
           SetWithExpression | 1,343.9223 ns | 38.2650 ns | 533.97 |
  • Adding some more validation may make sense. Maybe a debug assert checking that there is a property named property.Member.Name?
  • If you are using C#6 and this overload should be removed. Use nameof instead.
protected void OnPropertyChanged(string name)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(name));
    }
}
  • Good that you copy to a temp before nullchecking.
  • Depending on C# version [CallerMemberName] should be added like so:

    protected void OnPropertyChanged([CallerMemberName] string name = null)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.