thm*_*shd 30 .net c# events inotifypropertychanged
我正在寻找一个干净而优雅的解决方案来处理INotifyPropertyChanged嵌套(子)对象的事件.示例代码:
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
}
Run Code Online (Sandbox Code Playgroud)
关注BestFriend物业及其价值制定者.现在我知道我可以手动执行此操作,实现注释中描述的所有步骤.但这将是很多代码,特别是当我计划有许多这样的子属性实现时INotifyPropertyChanged.当然它们不会总是相同的类型,它们唯一的共同点就是INotifyPropertyChanged界面.
原因是,在我的实际场景中,我有一个复杂的"Item"(在购物车中)对象,它具有多个层的嵌套对象属性(Item有一个"License"对象,它本身可以再次有子对象)和我需要获得有关"项目"的任何单一更改的通知,以便能够重新计算价格.
你有什么好的建议甚至是一些实施来帮助我解决这个问题吗?
不幸的是,我无法/允许使用像PostSharp这样的后期构建步骤来实现我的目标.
非常感谢你提前,
- 托马斯
thm*_*shd 22
由于我无法找到一个现成的解决方案,我已经完成了基于Pieters(和Marks)建议的自定义实现(谢谢!).
使用这些类,您将收到有关深层对象树中任何更改的通知,这适用于任何INotifyPropertyChanged实现类型和INotifyCollectionChanged*实现集合(显然,我正在使用ObservableCollection它).
我希望这是一个非常干净和优雅的解决方案,它虽然没有经过充分测试,但仍有增强空间.它很容易使用,只需创建一个ChangeListener使用它的静态Create方法的实例并传递你的INotifyPropertyChanged:
var listener = ChangeListener.Create(myViewModel);
listener.PropertyChanged +=
new PropertyChangedEventHandler(listener_PropertyChanged);
Run Code Online (Sandbox Code Playgroud)
在PropertyChangedEventArgs提供PropertyName这将是永远的对象的完整"路径".例如,如果您更改了Persons的"BestFriend"名称,PropertyName则将为"BestFriend.Name",如果其中BestFriend包含Children的集合并且您更改它的Age,则该值将为"BestFriend.Children [].Age",因此上.不要忘记Dispose当你的对象被销毁时,它会(希望)完全取消订阅所有事件监听器.
它在.NET(测试4)和Silverlight(测试4)中编译.因为代码分为三个类,我已经将代码发布到gist 705450,你可以全部抓住它:https://gist.github.com/705450**
*)代码工作的一个原因是它ObservableCollection也实现了INotifyPropertyChanged,否则它不会按预期工作,这是一个众所周知的警告
**)免费使用,根据麻省理工学院许可证发布
Pie*_*kel 17
我认为你正在寻找的东西就像WPF绑定.
如果INotifyPropertyChanged工作是RaisePropertyChanged("BestFriend");必须的,只有在财产BestFriend变化时才能进行.当对象本身发生任何变化时.
如何实现这一点是通过一个两步INotifyPropertyChanged事件处理程序.您的听众将注册已更改的事件Person.当BestFriend被设置/改变,你的改变的情况下注册BestFriend Person.然后,您开始侦听该对象的已更改事件.
这正是WPF绑定实现这一点的方式.通过该系统监听嵌套对象的更改.
当你实现它时,它不起作用的原因是Person级别可以变得非常深,并且改变的事件BestFriend不再意味着什么("改变了什么?").当你有循环关系时,这个问题变得更大,例如你的最好的朋友是你最好的恶魔的母亲.然后,当其中一个属性发生更改时,会出现堆栈溢出.
那么,如何解决这个问题就是创建一个可以构建监听器的类.例如,您可以构建一个侦听器BestFriend.FirstName.然后,该类将在更改的事件上放置一个事件处理程序Person并监听更改BestFriend.然后,当它发生变化时,它会调出一个监听器BestFriend并监听其变化FirstName.然后,当它发生变化时,它会发送一个事件然后你就可以听了.这基本上是WPF绑定的工作原理.
有关WPF绑定的更多信息,请参见http://msdn.microsoft.com/en-us/library/ms750413.aspx.
| 归档时间: |
|
| 查看次数: |
37024 次 |
| 最近记录: |