NotifyOfPropertyChange()不通知viewmodel属性

时间:2017-06-02 17:13:10

标签: c# wpf mvvm caliburn.micro

我有一个简单的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并在单击保存按钮时设置一个标志,以便可以验证所有属性。

1 个答案:

答案 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;
};