c# - 如何在不将属性名称作为字符串传递的情况下引发 PropertyChanged 事件?

标签 c# wpf inotifypropertychanged

在 wpf 中,我们经常对可绑定(bind)属性使用以下模式:

private Foo _bar = new Foo();
public Foo Bar
{
    get { return _bar; }
    set
    {
        _bar = value;
        OnPropertyChanged();
    }
}

public void OnPropertyChanged([CallerMemberName] string property = "")
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(property));
}

CallerMemberNameAttribute施展魔法,根据 setter 名称为我们生成 "Bar" 参数。

但是,通常存在没有 setter 或依赖属性的属性:

private Foo _bar;
public Foo Bar
{
    get { return _bar; }
    set
    {
        _bar = value;
        OnPropertyChanged();
    }
}

public bool IsBarNull
{
    get { return _bar == null; }
}

在给定的示例中,当 Bar 发生更改时,IsBarNull 也需要事件。我们可以将 OnPropertyChanged("IsBarNull"); 添加到 Bar setter 中,但是...使用 string 属性是:

  • 丑陋的;
  • 难以重构(VS 的“重命名”不会重命名 string 中的属性名称);
  • 可能是各种错误的根源。

WPF存在了这么久。是否还没有神奇解决方案(类似于CallerMemberNameAttribute)?

最佳答案

使用 C# 6 和 nameof特点:

OnPropertyChange(nameof(IsBarNull));

生成的等效代码为:

OnPropertyChange("IsBarNull");

...但没有脆弱性。

如果您坚持使用早期版本的 C#,您可以为此使用表达式树,但我认为这有点 hack 和潜在的性能问题(因为树是重新创建的在每次通话中)。 nameof 不需要任何库支持,只需要一个新的编译器 - 所以如果你升级到 VS 2015(或更高版本,亲爱的 future 读者......)你应该没问题。

关于c# - 如何在不将属性名称作为字符串传递的情况下引发 PropertyChanged 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31472254/

相关文章:

wpf - 为什么 ViewModel 需要实现 INotifyPropertyChanged 或使用依赖属性?

c# - 如何处理 U-SQL EXTRACT 语句中丢失的文件?

c# - 如何在移动设备上的 Unity3d 中实现多点触控?

c# - 如何在静态类中使用 NLog,其中所有其他内容都与 Autofac 连接

c# - 功能区控件专注于按钮单击

wpf - 扩展器、网格和列表框 = 无虚拟化

c# - 未找到 WCF 服务端点

c# - Datagrid MVVM WPF中的复选框

winforms - Winforms 中的 ObservableCollection<T> 和可能的替代方案

c# - 如果我的类中没有具有该名称的相应属性,我是否应该引发 INotifyPropertyChanged 事件?