我有一个关于下面的代码问题:
public class MyClass : INotifyPropertyChanged
{
private bool _myProp;
public bool MyProp
{
get { return _myProp; }
set
{
_myProp = value;
RaisePropertyChanged(() => MyProp);
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
这可能不是识别属性名的最佳方式,但我以前也使用过它,即使在同一个项目; 然而,上面的代码将无法编译。 有几种变通办法此; 其中一些可能是更好的解决方案,什么是上面的,但是,我还是想找出为什么这是行不通的。
具体的编译错误我得到的是:
error CS1660: Cannot convert lambda expression to type 'string' because it is not a delegate type
你需要一个接受的方法Expression<Func<T>>
,提取属性名作为一个字符串,然后引发PropertyChanged
与它的事件。 它不会自动完成。 我通常使其成为一种扩展方法,以节省反复执行相同的代码或具有它的基类:
public static class RaisePropertyChangedExtensions
{
public static void RaisePropertyChanged<T>(
this IRaisePropertyChanged raisePropertyChangedImpl,
Expression<Func<T>> expr)
{
var memberExprBody = expr.Body as MemberExpression;
string property = memberExprBody.Member.Name;
raisePropertyChangedImpl.RaisePropertyChanged(property);
}
}
您的视图模型只需要实现IRaisePropertyChanged
接口:
public interface IRaisePropertyChanged : INotifyPropertyChanged
{
void RaisePropertyChanged(string property);
}
..和使用是完全一样在你的问题:
this.RaisePropertyChanged(() => MyProp);
当然,你总是可以让这对您的视图模型的方法 - 只是删除泛型参数,并通过您的视图模型类型的功能。
结帐新CallerMemberName属性。 我只能通过MVVM光发现了它,但绝不会不通知属性再次改变旧的方式。
http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx
您需要使用表达式:
public static string GetPropertyName<T, TPropValue>(this Expression<Func<T, TPropValue>> propertySelector) where T : class
{
Condition.Requires(propertySelector, "propertySelector").IsNotNull();
var memberExpr = propertySelector.Body as MemberExpression;
if (memberExpr == null)
throw new ArgumentException("Provider selector is not property selector.");
var propInfo = memberExpr.Member as PropertyInfo;
if (propInfo == null)
throw new NotSupportedException("You can properties only.");
return propInfo.Name;
}
protected void RaisePropertyChanged(Expression<Func<MyClass, string>> propSelector)
{
if (PropertyChanged != null)
{
var propertyName = propertySelecotr.GetPropertyName();
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
用法:
RaisePropertyChanged(myClass => myClass.MyProp);