WPF MVVM 模型的 DependencyProperty 模拟 [英] DependencyProperty analogue for WPF MVVM Model
问题描述
我有我的 MVVM,模型由许多相关的类组成,但为了这个问题,我们将只关注四个.
I have my MVVM and the model consists of a number of related classes, but for the sake of this question we'll focus on just four.
GrandParentModel、ParentModel、ChildModel 和 Contact.
GrandParentModel, ParentModel, ChildModel and Contact.
这些都继承自 ModelBase,它有一个 INotifyPropertyChanged 的实现.
These all inherit from ModelBase which has an implementation of INotifyPropertyChanged on it.
所以三个模型中的每一个都有一个 Contact 属性.如果 Child 没有属性,它应该查找 Parent,如果 Parent 为空,它将查找 GrandParent.如果联系人在祖父母级别发生变化,我希望任何受抚养人,即任何子父母和他们的孩子也为他们的联系人引发 PropertyChanged 事件.
So each of the three models has a Contact property. If Child doesn't have a property it is supposed to look to Parent, and if Parent is blank it will look to GrandParent. If the contact changes at the grandparent level I'd like any dependants, ie any sub parents and their children to raise a PropertyChanged event for their Contact too.
我认为我要做的一切都会得到 DependencyProperty 系统的支持,但我不想使用它,因为这是我的模型、关注点分离等等.所以我正在整理一个迷你实现,这一切都很好.
I think everything I'm going to do will be supported by the DependencyProperty system, but I don't want to use that as this is my Model, separation of concerns and all that. So I'm putting together a mini implementation, which is all fine.
我的问题是以前有人走过这条路吗,我将来有什么需要担心的吗?我的蜘蛛侠感觉刺痛,我不知道为什么.
My question is has anyone been down this path before and is there anything I should be worried about in the future? My Spidey-Senses are tingling and I don't know why.
谢谢伊恩
这里的对象之间的关系是祖父母有任意数量的父母有任意数量的孩子.我当前的模型在每个模型上都有一个指向父对象的属性(在祖父母的情况下为 null),并且父/祖父母有一组子对象.
The relationship between the objects here is that a grandparent has any number of parents has any number of children. My current model has a property on each which points at the parent (null in the case of a grandparent) and a parent/grandparent has a collection of child objects.
推荐答案
我一直在走这条路,但它并不漂亮.基本上,您必须从您的 ChildModel
订阅 ParentModel
的 PropertyChanged
事件.如果您的孩子可以更换父母,您必须小心.然后,当您从孩子的角度收到有关父更改的通知时,您必须在孩子上引发自己的 PropertyChanged
事件.它变得丑陋,因为您最终可能会挂起忘记清理的事件处理程序.
I've been down this path, and it's not pretty. Basically you have to subscribe to the PropertyChanged
event of ParentModel
from your ChildModel
. You have to take care if your child can change parents. Then when you get notified of a change in the parent from the child's point of view, you have to raise your own PropertyChanged
event on the child. It gets ugly because you can end up with hanging event handlers that you forgot to clean up.
更好的方法是创建您自己的模型特定的 DependencyProperty
模拟.基本上在您的 ChildModel
构造函数中,您声明"该属性 Contact
在为 null 时委托给对象 Parent
的属性 Contact
.您可以使用一个小助手类来执行此操作,该类观察 ParentModel
对象上的 PropertyChanged
事件,并让它在适当的时候在子对象上执行 PropertyChanged
事件.还要注意 Parent
属性在孩子上发生变化.
A better method would be to create your own Model-specific analog to DependencyProperty
. Basically in your constructor of ChildModel
you "declare" that property Contact
delegates to property Contact
of object Parent
when null. You do that using a little helper class that observes the PropertyChanged
event on the ParentModel
object and have it execute a PropertyChanged
event on the child when appropriate. Also have it watch for the Parent
property to change on the child.
您可以使用 MVVM Light 消息总线.让祖父母和父母在他们的 Contact
属性更改时都发送一条消息.让孩子聆听这些信息.当它收到一条消息时,然后检查它是否与它自己的父或祖父匹配,并在必要时引发 PropertyChanged
事件.这比上述任何一种方法都要好,因为您不必跟踪您的父母或祖父母何时发生变化.你不太可能有错误.它还使用弱引用,因此它不会像事件处理程序那样保留对象.
You could use the MVVM Light message bus. Have the grandparent and parent all send a message when their Contact
property changes. Have the child listen for those messages. When it gets a message, then check to see if it matches its own parent or grandparent, and raise a PropertyChanged
event if necessary. This is better than either method above because you don't have to keep track of when your parent or grandparent changes. You're less likely to have bugs. It also uses weak references, so it won't hold on to objects the way event handlers do.
现在我一直在做的是摆脱让我的模型对象实现 INotifyPropertyChanged
.我在模型和视图模型之间引入了一个 Presenter
层.Presenter
实际上是用小的 ViewModel小部件"(例如,一个小部件可能是一个 ChangeValue
小部件)构建了一个 ViewModel.我有一个规则引擎,它告诉 Presenter
如何从给定模型的小部件组成一个 ViewModel.Presenter
处理所有用户输入(基本上是针对模型执行 lambda),但由于它知道用户操作刚刚发生,因此它知道模型中的某些内容可能已更改.Model 操作完成后,它将所有数据从 Model 复制到 ViewModel.ViewModel 检查传入的数据并在字段实际更改时引发 PropertyChanged
事件.显然,这是最复杂的方法,但它为您提供了一个非常干净的模型,并且 ViewModel 和 Presenter 都不包含任何模型(域/业务)逻辑.
Now what I've been doing is getting away from having my model objects implement INotifyPropertyChanged
. I introduced a Presenter
layer between my Model and my ViewModel. The Presenter
actually constructs a ViewModel out of small ViewModel "widgets" (one widget might be a ChangeValue<T>
widget, for instance). I have a rules engine that tells the Presenter
how to compose a ViewModel out of widgets for a given Model. The Presenter
handles all user input (basically executing a lambda against the Model), but since it knows that a user action just took place, it knows that something in the Model might have changed. After the Model action is complete, it copies all of the data from the Model to the ViewModel. The ViewModel inspects the incoming data and raises a PropertyChanged
event if the field actually changed. Obviously that's the most compliated way of doing it, but it gives you a really clean Model and neither the ViewModel nor the Presenter contains any Model (domain/business) logic.
这篇关于WPF MVVM 模型的 DependencyProperty 模拟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!