我有一个简单的WPF应用程序,我想知道为什么NotifyOfPropertyChange()不能正常工作。我有一个带有两个属性和一个按钮的MainWindowViewModel,当我单击按钮时,我调用NotifyOfPropertyChange()来通知所有属性都已更改。我还有一个在ViewModel构造函数中编译的属性列表:
properties = typeof(MainWindowViewModel).GetProperties()
.Where(p => p.DeclaringType == typeof(MainWindowViewModel));
在构造函数中,我订阅了PropertyChanged:
PropertyChanged += (sender, args) =>
{
if (properties.Any(p => p.Name == args.PropertyName))
IsDirty = true;
};
这是我的整个MainViewModel:
public class MainWindowViewModel : Screen
{
private string name;
private IEnumerable<PropertyInfo> properties;
public string Name
{
get { return name; }
set
{
name = value;
NotifyOfPropertyChange(() => Name);
}
}
private int age;
public int Age
{
get { return age; }
set
{
age = value;
NotifyOfPropertyChange(() => Age);
}
}
private bool isDirty;
public bool IsDirty
{
get { return isDirty; }
set
{
isDirty = value;
NotifyOfPropertyChange(() => IsDirty);
}
}
public MainWindowViewModel()
{
// get list of class properties
properties = typeof(MainWindowViewModel).GetProperties()
.Where(p => p.DeclaringType == typeof(MainWindowViewModel));
// if any property has been updated, set isDirty to true
PropertyChanged += (sender, args) =>
{
if (properties.Any(p => p.Name == args.PropertyName))
IsDirty = true;
};
}
public void Save()
{
NotifyOfPropertyChange();
}
}
当应用程序运行时,构造函数会正确生成属性列表:Name,Age和IsDirty。但是,单击“保存”按钮时, 对于与viewmodel无关的其他属性引发PropertyChangedEvent:IsInitialized和IsActive,它们是屏幕的属性,不会为列表中的任何属性引发。有人能告诉我这里发生了什么或提供替代解决方案吗?我认为我非常清楚我要尝试做什么,这是一个验证场景,我需要调用一个PropertyChanged并在单击保存按钮时设置一个标志,以便可以验证所有属性。
答案 0 :(得分:1)
NotifyOfPropertyChange()方法的方法签名是:
public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
(链接到Caliburn.Micro github存储库:https://github.com/Caliburn-Micro/Caliburn.Micro/blob/master/src/Caliburn.Micro/PropertyChangedBase.cs#L44)
请注意CallerMemberName
属性。
在Save
方法中调用NotifyOfPropertyChange();
方法会导致 PropertyChanged 事件, PropertyChangedEventArgs.PropertyName 设置为“保存” (调用NotifyOfPropertyChange()的方法的名称)。那当然没有意义。
要表示您班级中的任何属性已更改,您必须明确传递null
或""
作为NotifyOfPropertyChange的参数(有效绕过 CallerMemberName 替换):
public void Save()
{
NotifyOfPropertyChange(null);
}
传递null
或空字符串作为属性名称有效。没有属性名称的PropertyChanged事件表示任何一个或多个属性已更改其值。
考虑到这一点,应该改进PropertyChanged事件处理程序,以正确地遵守没有属性名称的PropertyChanged事件:
PropertyChanged += (sender, args) =>
{
if (string.IsNullOrEmpty(args.PropertyName) || properties.Any(p => p.Name == args.PropertyName))
IsDirty = true;
};