为嵌套(子)对象订阅INotifyPropertyChanged [英] Subscribe to INotifyPropertyChanged for nested (child) objects

查看:172
本文介绍了为嵌套(子)对象订阅INotifyPropertyChanged的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


更新:解决问题,请参阅我的答案


我正在寻找一个干净的优雅的解决方案来处理嵌套(子)对象的 INotifyPropertyChanged 事件。示例代码:

  public class Person:INotifyPropertyChanged {

private string _firstName;
private int _age;
private Person _bestFriend;

public string FirstName {
get {return _firstName; }
set {
//简单实现简单原因
_firstName = value;
RaisePropertyChanged(FirstName);
}
}

public int Age {
get {return _ }
set {
//简单实现简单原因
_age = value;
RaisePropertyChanged(Age);
}
}

public Person BestFriend {
get {return _bestFriend;
set {
// - 取消订阅_bestFriend的INotifyPropertyChanged事件
//如果不是null

_bestFriend = value;
RaisePropertyChanged(BestFriend);

// - 订阅_bestFriend的INotifyPropertyChanged事件(如果不为空)
// - 当_bestFriend的INotifyPropertyChanged事件触发时,我想要
//具有RaisePropertyChanged(BestFriend )方法调用
// - 另外,我想有一些* weak *事件处理程序是必需的
//如果一个Person实例我蜂窝销毁
}
}

// ** INotifyPropertyChanged实现**
//实现RaisePropertyChanged方法

}

专注于 BestFriend 属性,它的值设置器。现在,我知道我可以手动执行,实现注释中描述的所有步骤。但是这将是很多的代码,特别是当我计划有许多子属性实现 INotifyPropertyChanged 这样。当然,它们并不总是相同的类型,唯一的共同之处就是 INotifyPropertyChanged 界面。



原因是,在我的实际情况下,我有一个复杂的项目(在购物车中)对象,它在多个层面上嵌套了对象属性(Item有一个许可证对象,它本身可以再次具有子对象),我需要收到关于项目的任何单一更改的通知,以便能够重新计算价格。



你有一些好的提示,甚至一些
实现帮助我解决
这个?



不幸的是,我不能/允许使用后期制作步骤像PostSharp一样完成我的目标。



提前非常感谢你,

- Thomas

解决方案

由于我无法找到即用的解决方案,我已经完成了基于Pieters(和Marks)建议的自定义实现(谢谢!) / p>

使用这些类,您会收到深层对象树中的任何更改的通知,这适用于任何 INotifyPropertyChanged 实现类型和 INotifyCollectionChanged *实现集合(显然,我正在使用 ObservableCollection )。



我希望这个原来是一个相当干净和优雅的解决方案,它没有完全测试,而且还有增强的空间。它很容易使用,只需创建一个 ChangeListener 的实例,使用它的静态创建方法并传递您的 INotifyPropertyChanged

  var listener = ChangeListener.Create(myViewModel); 
listener.PropertyChanged + =
new PropertyChangedEventHandler(listener_PropertyChanged);

PropertyChangedEventArgs 提供 PropertyName 它将始终是对象的完整路径。例如,如果您更改了Person的BestFriend名称,则 PropertyName 将为BestFriend.Name,如果 BestFriend 有一个孩子的集合,你改变它的年龄,值将是BestFriend.Children []。Age等等。不要忘记 Dispose ,当您的对象被销毁,那么(希望)完全取消订阅所有的事件监听器。



它在.NET中编译(测试4)和Silverlight(在4中测试)。由于代码分为三个类,我已将代码发布到 gist 705450 您可以抓住这一切: https://gist.github.com/705450 **



*)代码工作的一个原因是 ObservableCollection 还实现了 INotifyPropertyChanged ,否则它将无法正常工作,这是一个已知的警告



**)免费使用,在麻省理工学院许可证


UPDATE: Problem solved, see my Answer.

I'm looking for a clean and elegant solution to handle the INotifyPropertyChanged event of nested (child) objects. Example code:

public class Person : INotifyPropertyChanged {

  private string _firstName;
  private int _age;
  private Person _bestFriend;

  public string FirstName {
    get { return _firstName; }
    set {
      // Short implementation for simplicity reasons
      _firstName = value;
      RaisePropertyChanged("FirstName");
    }
  }

  public int Age {
    get { return _age; }
    set {
      // Short implementation for simplicity reasons
      _age = value;
      RaisePropertyChanged("Age");
    }
  }

  public Person BestFriend {
    get { return _bestFriend; }
    set {
      // - Unsubscribe from _bestFriend's INotifyPropertyChanged Event
      //   if not null

      _bestFriend = value;
      RaisePropertyChanged("BestFriend");

      // - Subscribe to _bestFriend's INotifyPropertyChanged Event if not null
      // - When _bestFriend's INotifyPropertyChanged Event is fired, i'd like
      //   to have the RaisePropertyChanged("BestFriend") method invoked
      // - Also, I guess some kind of *weak* event handler is required
      //   if a Person instance i beeing destroyed
    }
  }

  // **INotifyPropertyChanged implementation**
  // Implementation of RaisePropertyChanged method

}

Focus on the BestFriend Property and it's value setter. Now I know that I could do this manually, implementing all steps described in the comments. But this is going to be a lot of code, especially when I'm planning to have many child properties implementing INotifyPropertyChanged like this. Of course they are not going to be always of same Type, the only thing they have in common is the INotifyPropertyChanged interface.

The reason is, that in my real scenario, I have a complex "Item" (in cart) object which has nested object properties over several layers (Item is having a "License" object, which can itself have child objects again) and I need to get notified about any single change of the "Item" to be able to recalculate the price.

Do you some good tips or even some implementation to help me to solve this?

Unfortunately, I'm not able/allowed to use post-build steps like PostSharp to accomplish my goal.

Thank you very much in advance,
- Thomas

解决方案

since I wasn't able to find a ready-to-use solution, I've done a custom implementation based on Pieters (and Marks) suggestions (thanks!).

Using the classes, you will be notified about any change in a deep object tree, this works for any INotifyPropertyChanged implementing Types and INotifyCollectionChanged* implementing collections (Obviously, I'm using the ObservableCollection for that).

I hope this turned out to be a quite clean and elegant solution, it's not fully tested though and there is room for enhancements. It's pretty easy to use, just create an instance of ChangeListener using it's static Create method and passing your INotifyPropertyChanged:

var listener = ChangeListener.Create(myViewModel);
listener.PropertyChanged += 
    new PropertyChangedEventHandler(listener_PropertyChanged);

the PropertyChangedEventArgs provide a PropertyName which will be always the full "path" of your Objects. For example, if you change your Persons's "BestFriend" Name, the PropertyName will be "BestFriend.Name", if the BestFriend has a collection of Children and you change it's Age, the value will be "BestFriend.Children[].Age" and so on. Don't forget to Dispose when your object is destroyed, then it will (hopefully) completely unsubscribe from all event listeners.

It compiles in .NET (Tested in 4) and Silverlight (Tested in 4). Because the code in seperated in three classes, I've posted the code to gist 705450 where you can grab it all: https://gist.github.com/705450 **

*) One reason that the code is working is that the ObservableCollection also implements INotifyPropertyChanged, else it wouldn't work as desired, this is a known caveat

**) Use for free, released under MIT License

这篇关于为嵌套(子)对象订阅INotifyPropertyChanged的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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