如何在C# 6.0中实现INotifyPropertyChanged?

问题描述 投票:0回答:4

这个问题的答案已被编辑为在 C# 6.0 中,INotifyPropertyChanged 可以通过以下 OnPropertyChanged 过程实现:

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

但是,从该答案中并不清楚相应的属性定义应该是什么。使用此构造时,C# 6.0 中 INotifyPropertyChanged 的完整实现是什么样子?

c# inotifypropertychanged c#-5.0 c#-6.0
4个回答
34
投票

合并各种更改后,代码将如下所示。我用评论突出显示了更改的部分以及每个部分如何提供帮助

public class Data : INotifyPropertyChanged
{ 
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        //C# 6 null-safe operator. No need to check for event listeners
        //If there are no listeners, this will be a noop
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // C# 5 - CallMemberName means we don't need to pass the property's name
    protected bool SetField<T>(ref T field, T value,
    [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) 
            return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    private string name;
    public string Name
    {
        get { return name; }
        //C# 5 no need to pass the property name anymore
        set { SetField(ref name, value); }
    }
}

15
投票

我在我的项目中使用相同的逻辑。我的应用程序中的所有视图模型都有一个基类:

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class PropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

每个视图模型都继承自该类。现在,在每个属性的设置器中我只需要调用

OnPropertyChanged()

public class EveryViewModel : PropertyChangedBase
{
    private bool initialized;
    public bool Initialized
    {
        get
        {
            return initialized;
        }
        set
        {
            if (initialized != value)
            {
                initialized = value;
                OnPropertyChanged();
            }
        }
    }

为什么有效?

编译器会自动使用调用此函数的成员的名称填充

[CallerMemberName]
。当我们从
OnPropertyChanged
调用
Initialized
时,编译器将
nameof(Initialized)
作为参数传递给
OnPropertyChanged

另一个需要记住的重要细节

框架要求

PropertyChanged
以及您绑定到的所有属性都是
public


5
投票

我知道这个问题很旧,但这是我的实现

Bindable 使用字典作为属性存储。为子类添加必要的重载以使用 ref 参数管理其自己的支持字段非常容易。

  • 没有魔法绳
  • 没有反射
  • 可以改进以抑制默认字典查找

代码:

    public class Bindable : INotifyPropertyChanged
    {
        private Dictionary<string, object> _properties = new Dictionary<string, object>();

        /// <summary>
        /// Gets the value of a property
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        protected T Get<T>([CallerMemberName] string name = null)
        {
            object value = null;
            if (_properties.TryGetValue(name, out value))
                return value == null ? default(T) : (T)value;
            return default(T);
        }

        /// <summary>
        /// Sets the value of a property
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="name"></param>
        protected void Set<T>(T value, [CallerMemberName] string name = null)
        {
            if (Equals(value, Get<T>(name)))
                return;
            _properties[name] = value;
            OnPropertyChanged(name);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

这样使用

public class Item : Bindable
{
     public Guid Id { get { return Get<Guid>(); } set { Set<Guid>(value); } }
}

0
投票

您可以考虑使用为您生成代码的工具,而不是在所有类中手动实现 INotifyPropertyChanged(这可能需要大量样板代码)。有多种工具可用:

© www.soinside.com 2019 - 2024. All rights reserved.