patterncsharpMinor
Improvements to a ViewModelBase
Viewed 0 times
improvementsviewmodelbasestackoverflow
Problem
Every time I go to write an MVVM application (say every 4-6 months) I rewrite my
So I rewrite the basic
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 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(Expression> 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.Solution
I've used the below for a while:
I can write my properties like this:
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(ref T backingField, T Value, Expression> propertyExpression)
{
var changed = !EqualityComparer.Default.Equals(backingField, Value);
if (changed)
{
backingField = Value;
this.RaisePropertyChanged(ExtractPropertyName(propertyExpression));
}
return changed;
}
private static string ExtractPropertyName(Expression> 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);
}
}Code Snippets
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;
}
}private int id;
public int Id
{
get
{
return this.id;
}
set
{
this.SetProperty(ref this.id, value, () => this.Id);
}
}Context
StackExchange Code Review Q#13823, answer score: 7
Revisions (0)
No revisions yet.