NotifyOfPropertyChange() 没有通知视图模型属性

NotifyOfPropertyChange() is not notifying viewmodel properties

我有一个简单的 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。但是,当单击保存按钮时, PropertyChangedEvent 是针对与视图模型无关的其他属性引发的:IsInitialized 和 IsActive,它们是屏幕的属性,并且不会针对列表中的任何属性引发。有人可以告诉我这里发生了什么或提供替代解决方案吗?我想我想做什么很清楚,这是一个验证场景,如果单击保存按钮,我需要调用 PropertyChanged 并设置一个标志,以便验证所有属性。

NotifyOfPropertyChange() 方法的方法签名是:

public virtual void NotifyOfPropertyChange([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)

(Link 到 Caliburn.Micro github 存储库:https://github.com/Caliburn-Micro/Caliburn.Micro/blob/master/src/Caliburn.Micro/PropertyChangedBase.cs#L44)

注意 CallerMemberName 属性。

Save 方法中调用它,如 NotifyOfPropertyChange(); 将导致带有 PropertyChangedEventArgs.PropertyName 的 PropertyChanged 事件 设置为 "Save"(调用 NotifyOfPropertyChange() 的方法的名称)。那当然没有意义。

要表明 class 中的任何 属性 已更改,您必须显式传递 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;
};