如何避免手动实现INotifyPropertyChanged

有没有办法避免这种情况。 我有很多绑定到DataGridViews的类,它们只是带有默认getter和setter的简单属性集合。 所以这些类非常简单。 现在我需要为它们实现INotifyPropertyChanged接口,这将增加很多代码量。 是否有任何类可以inheritance以避免编写所有这些无聊的代码? 我认为我可以从某个类inheritance我的类,并用一些属性装饰属性,它会发挥魔力。 那可能吗?

我很清楚面向方面编程,但我宁愿以面向对象的方式。

创建容器基类,例如:

abstract class Container : INotifyPropertyChanged { Dictionary values; protected object this[string name] { get {return values[name]; } set { values[name] = value; PropertyChanged(this, new PropertyChangedEventArgs(name)); } } } class Foo : Container { public int Bar { {get {return (int) this["Bar"]; }} {set { this["Bar"] = value; } } } } 

注意:非常简化的代码

这取决于; 你可以使用PostSharp来编写由weaver重写的这样一个属性; 但是,我很想手动完成它 – 也许使用一种常用的方法来处理数据更新,即

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

有:

 public static class Notify { public static bool SetField(ref T field, T value, PropertyChangedEventHandler handler, object sender, string propertyName) { if(!EqualityComparer.Default.Equals(field,value)) { field = value; if(handler!=null) { handler(sender, new PropertyChangedEventArgs(propertyName)); } return true; } return false; } } 

没有AOP,我认为没有一种简单的方法可以将其改进现有的类。 无论如何,您至少需要更改所有属性。

我使用一个inheritanceINotifyPropertyChanged的基类和一个OnPropertyChanged(string propertyName)方法来触发事件。 然后,我使用Visual Studio代码片段创建在属性设置器中自动调用OnPropertyChanged的属性。

这是Marc的类似解决方案,已经扩展到允许多个属性onpropertychanges和多个RaiseCanExecuteChanged

最简单的示例用法

 string _firstName; public string FirstName { get { return _firstName; } set { OnPropertyChanged(ref _firstName, value, "FirstName"); } } 

使用多个属性更新和多个命令的高级示例

 string _firstName; public string FirstName { get { return _firstName; } set { OnPropertyChanged(ref _firstName, value, "FirstName", "FullName", Command1, Command2); } } 

高级示例调用OnProperty在firstname和fullname上更改,并且还为command1和command2调用RaiseCanExecuteChanged

基本ViewModel代码

 protected void OnPropertyChanged(ref T field, T value, params object[] updateThese) { if (!EqualityComparer.Default.Equals(field, value)) { field = value; OnPropertyChanged(updateThese); } } protected void OnPropertyChanged(params object[] updateThese) { if (PropertyChanged != null) { foreach (string property in updateThese.Where(property => property is string)) PropertyChanged(this, new PropertyChangedEventArgs(property)); foreach (DelegateCommand command in updateThese.Where(property => property is DelegateCommand)) command.RaiseCanExecuteChanged(); } } 

如果您适合AOP,可以尝试使用PostSharp 。 搜索PostSharp INotifyPropertyChanged,你会发现很多解释它的文章,比如这个和这个 。

使用代码gen(比方说, T4 )是另一种方式。 检查讨论: 通过T4代码生成自动INotifyPropertyChanged实现? 。

我使用这种方法,效果很好。

我刚刚找到ActiveSharp – 自动INotifyPropertyChanged ,我还没有使用它,但它看起来不错。

引用它的网站……


发送属性更改通知,而不指定属性名称作为字符串。

相反,写这样的属性:

 public int Foo { get { return _foo; } set { SetValue(ref _foo, value); } // <-- no property name here } 

请注意,不需要将属性的名称包含在字符串中。 ActiveSharp可靠而正确地为自己找出答案。 它的工作原理是您的属性实现通过ref传递了支持字段(_foo)。 (ActiveSharp使用“by ref”调用来识别传递了哪个支持字段,并从字段中识别属性)。