实施 INotifyPropertyChanged - 是否存在更好的方法? [英] Implementing INotifyPropertyChanged - does a better way exist?

查看:23
本文介绍了实施 INotifyPropertyChanged - 是否存在更好的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Microsoft 应该为 INotifyPropertyChanged 实现一些活泼的东西,就像在自动属性中一样,只需指定 {get;放;通知;}我认为这样做很有意义.或者有什么复杂的事情要做吗?

Microsoft should have implemented something snappy for INotifyPropertyChanged, like in the automatic properties, just specify {get; set; notify;} I think it makes a lot of sense to do it. Or are there any complications to do it?

我们可以自己在我们的属性中实现类似通知"的东西吗?是否有一种优雅的解决方案可以在您的类中实现 INotifyPropertyChanged,或者唯一的方法是在每个属性中引发 PropertyChanged 事件.

Can we ourselves implement something like 'notify' in our properties. Is there a graceful solution for implementing INotifyPropertyChanged in your class or the only way to do it is by raising the PropertyChanged event in each property.

如果不能,我们可以写一些东西来自动生成一段代码来引发 PropertyChanged 事件吗?

If not can we write something to auto-generate the piece of code to raise PropertyChanged event?

推荐答案

没有使用类似 postsharp 的东西,我使用的最小版本使用了类似的东西:

Without using something like postsharp, the minimal version I use uses something like:

public class Data : INotifyPropertyChanged
{
    // boiler-plate
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    // props
    private string name;
    public string Name
    {
        get { return name; }
        set { SetField(ref name, value, "Name"); }
    }
}

然后每个属性就像:

private string name;
public string Name
{
    get { return name; }
    set { SetField(ref name, value, "Name"); }
}

这不是很大;如果需要,它也可以用作基类.从 SetField 返回的 bool 告诉您它是否为空操作,以防您想应用其他逻辑.

which isn't huge; it can also be used as a base-class if you want. The bool return from SetField tells you if it was a no-op, in case you want to apply other logic.

使用 C# 5 甚至更容易:

or even easier with C# 5:

protected bool SetField<T>(ref T field, T value,
    [CallerMemberName] string propertyName = null)
{...}

可以这样调用:

set { SetField(ref name, value); }

编译器会自动添加Name".

C# 6.0 使实现更容易:

C# 6.0 makes the implementation easier:

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


...现在使用 C#7:


...and now with C#7:

protected void OnPropertyChanged(string propertyName)
   => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

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 => name;
    set => SetField(ref name, value);
}


而且,对于 C# 8 和 Nullable 引用类型,它看起来像这样:


And, with C# 8 and Nullable reference types, it would look like this:

public event PropertyChangedEventHandler? PropertyChanged;

protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(propertyName);
    return true;
}

private string name;
public string Name
{
    get => name;
    set => SetField(ref name, value);
}

这篇关于实施 INotifyPropertyChanged - 是否存在更好的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆