实现INotifyPropertyChanged时的属性获取器和设置器

本文关键字:设置 获取 属性 INotifyPropertyChanged 实现 | 更新日期: 2023-09-27 18:19:35

我正在尝试为许多类实现INotifyPropertyChanged,其中每个类都有很多属性。关于如何实现INofifyPropertyChanged,我一直在遵循MSDN文档,但在类具有许多属性的情况下,它们的说明似乎并不实用。

目前,我的大多数房产都使用短手:

public DateTime? DateClosed { get; set; }

但文档中说,我需要在每个setter方法中添加以下内容:

// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("DateClosed");

这意味着我需要为get方法声明一个主体,并声明私有变量来处理属性的实际获取和设置。像这样:

private DateTime? _dateOfIncident = null;
public DateTime? DateClosed
{
    get { return _dateOfIncident; }
    set
    {
        _dateOfIncident= value;
        // Call OnPropertyChanged whenever the property is updated
          OnPropertyChanged("DateClosed");
    }
}

有人知道这方面的办法吗?

实现INotifyPropertyChanged时的属性获取器和设置器

可以很容易地更改一些类来实现INotifyPropertyChanged。但是,由于您声明有许多类具有许多属性,因此手动或使用模板完成这项工作确实是一种负担。

你真正需要的是一个为你做这件事的工具,所以我向你展示Fody,它是NotifyPropertyChanged插件。Fody所做的是在编译时在代码之间编织一些额外的代码。您唯一需要做的就是在要实现INotifyPropertyChanged的类上添加一个属性,剩下的就为您完成了。

[ImplementPropertyChanged]
public class Person 
{        
    public string GivenNames { get; set; }
    public string FamilyName { get; set; }
    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }
}

我不确定你会在这里找到解决方法。正如您现在使用的那样,自动属性实际上只是一种编译器的简写,它最终会被转换为带有支持字段的完整属性(至少,据我所知)。

INPC的使用是一种例行程序,有点独立于正常属性的职责。它通知订阅者(通常是您的视图XAML)有问题的属性已经更改或正在更改。

tl;dr--您将无法避免将自动属性重写为带有后台字段的完整属性。但像MVVMLight这样的工具包有一些很棒的VisualStudio代码片段,可以使其相对快速。最终你甚至可以做到这一点:

private string _someString;
public string SomeString
{
    get { return _someString;}
    set 
    {
            //Set returns bool, so you can trigger other logic on it! 
            Set(() => SomeString, ref _someString, value);
    }
}

这给了你一些巧妙的功能:

  • 强命名(与示例中的魔术串不同)
  • Set仅在值不同时触发INPC事件
  • Set返回布尔值,以便在值发生更改时可以执行更多操作

MVVMLight的优点在于,您不必使用它的所有功能,甚至不必实现MVVM模式。它只是有很多不错的"工具",你可以利用。

有很多模式可以做到这一点,或者你可以买一个像PostSharp这样的工具来为你做这件事。

例如,这里有一种方法:

public abstract class BaseNotifyPropertyChanged : INotifyPropertyChanged
{
    private Dictionary<string, object> _valueStore = new Dictionary<string, object>();
    public event PropertyChangedEventHandler PropertyChanged;
    protected T Get<T>([CallerMemberName]string property = null)
    {
        object value = null;
        if (!_valueStore.TryGetValue(property, out value))
            return default(T);
        return (T)value;
    }
    protected void Set<T>(T value, [CallerMemberName]string property = null)
    {
        _valueStore[property] = value;
        OnPropertyChangedInternal(property);
    }
    protected void OnPropertyChanged([CallerMemberName]string property = null)
    {
        OnPropertyChangedInternal(property);
    }
    private void OnPropertyChangedInternal(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

然后从类中继承:

public class PlainOldObject : BaseNotifyPropertyChanged
{
    public int MyProperty
    {
        get { return Get<int>(); }
        set { Set(value); }
    }
}

它为您处理后备存储和所有事务。您可能希望添加仅在属性实际更改(比较引用或值)时调用OnPropertyChangedInternal的逻辑,但我将把它留给您练习。

只需使用Observable Object类。不创建DateTime属性,而是创建一个ObservableObject<DateTime>,然后只绑定到DateClosed.Value