在下面的例子中,您需要传递3个值(后备字段,新值,作为lambda的属性),但没有魔法字符串,并且仅在属性真正不相等时才会触发属性更改事件。
class Sample : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set { this.SetProperty(ref _name, value, () => this.Name); }
}
protected void SetProperty<T>(ref T backingField, T newValue, Expression<Func<T>> propertyExpression)
{
if (backingField == null && newValue == null)
{
return;
}
if (backingField == null || !backingField.Equals(newValue))
{
backingField = newValue;
this.OnPropertyChanged(propertyExpression);
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyExpression.GetPropertyName()));
}
}
}
以下代码包含了从Lambda表达式中获取属性名称的扩展方法。
public static class Extensions
{
public static string GetPropertyName<TProperty>(this Expression<Func<TProperty>> propertyExpression)
{
return propertyExpression.Body.GetMemberExpression().GetPropertyName();
}
public static string GetPropertyName(this MemberExpression memberExpression)
{
if (memberExpression == null)
{
return null;
}
if (memberExpression.Member.MemberType != MemberTypes.Property)
{
return null;
}
var child = memberExpression.Member.Name;
var parent = GetPropertyName(memberExpression.Expression.GetMemberExpression());
if (parent == null)
{
return child;
}
else
{
return parent + "." + child;
}
}
public static MemberExpression GetMemberExpression(this Expression expression)
{
var memberExpression = expression as MemberExpression;
if (memberExpression != null)
{
return memberExpression;
}
var unaryExpression = expression as UnaryExpression;
if (unaryExpression != null)
{
memberExpression = (MemberExpression)unaryExpression.Operand;
if (memberExpression != null)
{
return memberExpression;
}
}
return null;
}
public static void ShouldEqual<T>(this T actual, T expected, string name)
{
if (!Object.Equals(actual, expected))
{
throw new Exception(String.Format("{0}: Expected <{1}> Actual <{2}>.", name, expected, actual));
}
}
}
最后是一些测试代码:
class q3191536
{
public static void Test()
{
var sample = new Sample();
var propertyChanged = 0;
sample.PropertyChanged +=
new PropertyChangedEventHandler((sender, e) =>
{
if (e.PropertyName == "Name")
{
propertyChanged += 1;
}
}
);
sample.Name = "Budda";
sample.Name.ShouldEqual("Budda", "sample.Name");
propertyChanged.ShouldEqual(1, "propertyChanged");
sample.Name = "Tim";
sample.Name.ShouldEqual("Tim", sample.Name);
propertyChanged.ShouldEqual(2, "propertyChanged");
sample.Name = "Tim";
sample.Name.ShouldEqual("Tim", sample.Name);
propertyChanged.ShouldEqual(2, "propertyChanged");
}
}
INPC
让生活变得非常容易,而不必担心属性名称的更改和打字错误。 - Mohsen Afshin