c# - NotifyOfPropertyChange()通知 View 模型属性

标签 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();
    }
}

当应用程序运行时,构造函数会正确生成属性列表:名称,年龄和IsDirty。但是,单击“保存”按钮后,
对于与 View 模型不相关的其他属性,引发PropertyChangedEvent:IsInitialized和IsActive,它们是屏幕的属性,对于列表中的任何属性都不引发。有人可以告诉我这是怎么回事还是提供替代解决方案?我认为我想做的很清楚,这是一个验证方案,如果单击保存按钮,则需要调用PropertyChanged并设置一个标志,以便可以验证所有属性。

最佳答案

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设置为“Save”(调用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;
};

关于c# - NotifyOfPropertyChange()通知 View 模型属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44334210/

相关文章:

c# - 从服务器端在 asp.net 中将内容添加到 Bootstrap 模式中的 div

c# - MVVM Light EventToCommand - 无法触发事件

wpf - 如何禁用堆栈面板上的制表位

c# - WPF 绑定(bind)到特定属性

wpf - MVVM、集合和 ORM

c# - 使用 LINQ 获取 IEnumerable 中的上一个和下一个项目

c# - AudioSource的Unity3D共享设置

c# - 验证规则

c# - 如何将 XPS 文件中的每一页转换为 C# 中的图像?

c# - WPF:ObservableCollection 内存泄漏