如何为属性更改通知编写更少的样板?

vir*_*tor 5 c# wpf mvvm

我有一个类似 MVVM 的应用程序,最终得到的模型包含太多属性更改通知。具体来说,我有时会错过一些通知,因为通知太多。

例如,我最终得到这样的属性:

public string CustomEmail {
    get => customEmail;
    set
    {
        customEmail = value;
        OnChanged("CustomEmail");
        OnChanged("IsSendAllowed");
        OnChanged("IsNotFaxEmail");
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来组织它?例如,有没有办法标记属性[DependsOn("CustomEmail")] bool IsNotFaxEmail { ... }

或者,如果大多数属性都用于绑定,我应该全力使用转换器吗?我不想最终得到像{Binding CustomEmail, Converter=EmailIsFaxToElementVisibilityConverter}.

我是否缺少一些更简单的解决方案?

And*_*ndy 6

我不经常发现这么多的依赖项,但我可以概述我见过的解决方案。创建一个属性。将其称为 AlsoRaise 属性,它采用字符串参数。你也许可以想出一个更好的名字。但我认为 dependent 不太正确,因为它是相反的。

[AlsoRaise(nameof(IsSendAllowed))]
[AlsoRaise(nameof(IsNotFaxEmail))]
public string CustomEmail
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用一些东西来驱动您要为其发出更改通知的其他属性以及 CustomEmail 的列表。

在静态构造函数中,您可以使用这些属性填充字典<string, string[]>。您迭代公共属性,获取这些属性。

在 OnChanged 中,您在该字典中查找属性名称,并根据属性名称加上您找到的任何字符串引发属性更改。或者当然没有。

自从我看到这个实现以来,我可能已经忘记了某些部分。


Cle*_*ens 5

您可以编写接受多个属性名称的 NotifyPropertyChanged 方法。它并没有真正减少代码量,但至少允许只进行一个方法调用。

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(params string[] propertyNames)
    {
        var propertyChanged = PropertyChanged;

        if (propertyChanged != null)
        {
            foreach (var propertyName in propertyNames)
            {
                propertyChanged.Invoke(this,
                   new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

public class ViewModel : ViewModelBase
{
    private string customEmail;

    public string CustomEmail
    {
        get => customEmail;
        set
        {
            customEmail = value;

            NotifyPropertyChanged(
                nameof(CustomEmail),
                nameof(IsSendAllowed),
                nameof(IsNotFaxEmail));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)