当值改变或set被调用时,我应该引发INotifyPropertyChanged吗?

本文关键字:我应该 INotifyPropertyChanged 改变 set 调用 | 更新日期: 2023-09-27 18:12:19

实现INotifyPropertyChanged时,PropertyChanged应该只在n != value被调用时才被调用,还是应该因为set被调用而被调用?

我在这里寻找的是一个行业标准建议(如果存在的话),哪个实现更好,为什么。

例1 -说明一个"哑"事件引发策略

class Person : INotifyPropertyChanged
{
    private string name;
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            PropertyChanged(this, new PropertyChangedEventArgs(nameof(Name)));
        }
    }
}

用例1

Person p = new Person();
p.Name = "John"; // ProperyChanged fired
p.Name = "John"; // ProperyChanged fired

例2-说明一个"聪明的"事件引发策略

class Person : INotifyPropertyChanged
{
    private string name;
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            if(name != value)
            {
                name = value;
                PropertyChanged(this, new PropertyChangedEventArgs(nameof(Name)));
            }
        }
    }
}

用例2

Person p = new Person();
p.Name = "John"; // ProperyChanged fired
p.Name = "John"; // ProperyChanged ignored as name == value

请注意例2中的if(name != value),它只允许值更改,当传入值与现有值不匹配时,ProperyChanged事件。

当值改变或set被调用时,我应该引发INotifyPropertyChanged吗?

顾名思义,INotifyPropertyChanged,根据msdn:

INotifyPropertyChanged接口用于通知客户端,通常是绑定客户端,属性值已经更改。

最好只在值发生变化时触发事件。

https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged (v = vs.110) . aspx

典型的实现模式是这样的:
public string Foo
{
    get { return _foo; }
    set
    {    
        if (string.Equals(_foo, value)) return;
        _foo= value;
        OnPropertyChanged();
    }
}

顺便说一下,这也是ReSharper的约定,可以在这里找到;https://www.jetbrains.com/help/resharper/2016.1/Coding_Assistance__INotifyPropertyChanged_Support.html

作为旁注:仅在更改值时触发将保护您在更新从其他值计算的值时免受循环依赖。

:考虑以下代码:

public string DependentFoo
{
    get { return _foo; }
    set
    {    
        if (string.Equals(_foo, value)) return;
        _foo= value;
        //if some condition:
        DependentBar = "";
        OnPropertyChanged();
    }
}
public string DependentBar
{
    get { return _bar; }
    set
    {    
        if (string.Equals(_bar, value)) return;
        _bar = value;
        //if some condition:
        DependentFoo = "";
        OnPropertyChanged();
    }
}

虽然这不是一个很好的例子,但我认为你会明白的。

INotifyPropertyChanged的文档说这个接口的目的是

通知客户端属性值发生了变化。

这显然是指"属性值"的变化。文档页中的示例也使用了示例2中的模式。

没有"正确"的方法。这完全取决于你需要它做什么。例如:

如果你需要的只是更新GUI,那么我想说,当属性实际上没有改变时,调用PropertyChanged是不必要的。但是,如果您想将事件用于其他目的(例如日志记录或类似的东西),那么它绝对是一个解决方案。