实现INotifyPropertyChanged时的属性Getters和Setter?

时间:2015-10-28 14:55:25

标签: c# .net winforms inotifypropertychanged

我正在尝试为很多类实现INotifyPropertyChanged,并且每个类都有很多很多属性。我一直在关注如何实现INofifyPropertyChanged这个MSDN documentation,但是在类具有许多属性的情况下,它们的指令似乎并不实用。

目前我的大部分物业都使用简写:

public DateTime? DateClosed { get; set; }

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

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

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

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

有没有人知道解决这个问题的方法?

4 个答案:

答案 0 :(得分:1)

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

使用INPC是一种常规,与正常财产的职责分开。它通知订阅者(通常是您的视图XAML)相关属性已更改或正在更改。

tl; dr - 您不会不得不使用支持字段将autoproperties重写为完整属性。但像MVVMLight这样的工具包有一些很棒的Visual Studio代码片段可以让它相对快速。最终你甚至可以这样做:

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模式。它只是有许多你可以利用的好工具。

答案 1 :(得分:1)

可以轻松更改几个类来实现Holder。但是既然你声明你已经很多具有很多属性的类,那么手动完成或者甚至使用模板来实现这一点是一个真正的负担。

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

INotifyPropertyChanged

答案 2 :(得分:0)

有很多模式可以做,或者你可以购买一个可以为你做的工具like 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(比较引用或值),但我会将其作为练习留给您。

答案 3 :(得分:0)

只需使用Observable Object课程即可。您不必创建DateTime属性,而是创建ObservableObject<DateTime>,而只需绑定到DateClosed.Value