There are many ways notifying on property changed, and I think the most popular one is using the lambda expression solution:
public class Ball : Model
{
private double _velocity;
public double Velocity
{
get { return _velocity; }
set
{
if (_velocity != value)
{
_velocity = value;
NotifyPropertyChanged(() => Velocity);
}
}
}
}
I’ve to say that using the lambda solution is cool and type safety.
But, why should I bother creating a field member for each property, set it only if not equals to the new value and only then call the NotifyPropertyChanged method?
I would like to do something like this:
public class Ball : Model
{
public double Velocity
{
get { return GetValue(() => Velocity); }
set { SetValue(() => Velocity, value); }
}
}
And to do so the Model class should derive from this class:
public abstract class NotifyingObject : INotifyPropertyChanged
{
private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
public event PropertyChangedEventHandler PropertyChanged;
protected void SetValue<T>(Expression<Func<T>> propertySelector, T value)
{
string propertyName = GetPropertyName(propertySelector);
_values[propertyName] = value;
NotifyPropertyChanged(propertySelector);
}
protected T GetValue<T>(Expression<Func<T>> propertySelector)
{
string propertyName = GetPropertyName(propertySelector);
object value;
if (_values.TryGetValue(propertyName, out value))
{
return (T)value;
}
return default(T);
}
protected void NotifyPropertyChanged<T>(Expression<Func<T>> propertySelector)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
string propertyName = GetPropertyName(propertySelector);
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
protected void NotifyPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string GetPropertyName(LambdaExpression expression)
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
{
throw new InvalidOperationException();
}
return memberExpression.Member.Name;
}
}
Of course you can extend this solution by adding actions before and after changing the value, add coercing, validation and other goodies from WPF DependencyProperty in generic, new fashion way.
public double Velocity
{
get { return GetValue(() => Velocity); }
set
{
SetValue(
() => Velocity,
value,
(oldValue, newValue) => Debug.WriteLine(string.Format("{0}, {1}", oldValue, newValue)), // Callback
newValue => Math.Max(Math.Min(10, newValue), 0), // Coercing
newValue => newValue != null); // Validation
}
}
Nice Coding!