在实现INotifyPropertyChanged
时,我一直不确定propertyName
的含义。所以通常你实现INotifyPropertyChanged
为:
public class Data : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName = "") {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
private string itsID;
public string ID {
get { return itsID; }
set {
if (itsID != value) {
itsID = value;
NotifyPropertyChanged("ID");
}
}
}
我从来不确定propertyName
对NotifyPropertyChanged(string propertyName)
的论证。
- 可以是任何任意字符串(如"MyID"在上面的例子)? 或者。net使用反射来与类中的属性对齐,所以它必须与属性的名称完全匹配?
- 如果
propertyName
与Property
的名称不完全匹配,那么。net是否将整个对象视为changed
?
这不是。net框架本身,而是几乎每个PropertyChanged
订阅者(其中一些确实碰巧作为框架的一部分分发)都假设您通过发送属性名按预期使用接口。如果您发送属性MyID
已更改的通知,当另一个组件查看属性ID
时,它通常会看到通知,比较名称,并得出"此通知不适合我"的结论。
如果你想完全匹配属性的名称,你可以使用c# 6的新特性nameof
。nameof
特性回答了你所有的问题,因为我们可以说,用一个词来描述nameof
的主要优点是重构。根据你的问题,"重构"是你要找的词:
NotifyPropertyChanged(nameof(ID));
作为一个例子,重命名ID
也会改变属性的名称,或者它会破坏编译,但以下代码不会:
NotifyPropertyChanged("ID")
必须与属性的名称完全匹配。另外,您应该在调用PropertyChanged之前检查值是否已经实际更改,因为这是一个相对昂贵的调用(WPF不会知道属性没有更改)。在VS2015中,您还可以使用操作符的名称
根据INotifyPropertyChanged Interface页面,您可以保留未定义的propertyName
参数。原因如下:
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String
propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
注意参数中的[CallerMemberName]属性。这将自动将属性的名称替换为字符串,而无需静态地定义它。文档还指定:
PropertyChanged事件可以通过使用
null
或String.Empty
作为PropertyChangedEventArgs
中的属性名来指示对象上的所有属性已经更改。请注意,在UWP应用程序中,必须使用String.Empty
而不是null。
这一切都是为了方便您手动处理特定控件或整个表单的更改。INotifyPropertyChanged
接口没有定义NotifyPropertyChanged
方法,因此必须事先了解CallerMemberName
属性。