ViewModel 到 ViewModel 的通信
给定以下场景:
- ViewModelA 启动 ViewModelB(当然,通过通用控制器,该控制器使用 Ioc 和 DI 来解析所需的类型)。
- ViewModelB需要在ViewModelA中设置一个属性值。
简单地通过构造函数注入将 ViewModelA 注入 ViewModelB 并直接设置属性是否不好?
或者……
是否应该使用像 Prism 的 EventAggregator 这样的消息系统来处理 ViewModel 之间的所有通信?
我喜欢注射方法,因为它很简单,但我的直觉告诉我我错过了一些东西。我呼吁你们的集体智慧来帮助填补我的盲点。
Given the following scenario:
- ViewModelA launches ViewModelB (via a common Controller, of course, that uses Ioc and DI to resolve the types needed).
- ViewModelB needs to set a property value in ViewModelA.
Is it bad to simply inject ViewModelA into ViewModelB via constructor injection and just set the property directly?
Or…
Should a messaging system like the EventAggregator from Prism be used to handle all communication between ViewModels?
I like the injection approach because it’s easy, but my instincts are telling me I’m missing something. I call on your collective wisdom to help fill in my blind spot.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
更多
发布评论
评论(4)
如果您需要双向引用,我认为这是一种代码味道。通常,您可以用事件替换其中一个引用。
让 ViewModelB 引发 ViewModelA 订阅的事件。像 Prism 中那样的完整消息传递系统当然是一种选择,但在您的场景中,听起来“正常”事件就可以了。
I consider it a code smell if you need two-way references. Often you can replace one of the references with an event.
Let ViewModelB raise an event that ViewModelA subscribes to. A complete messaging system like the one found in Prism is certainly an option, but in your scenario it sounds like a 'normal' event will do just fine.
我建议您阅读这个问题(和我的答案),因为它很相似,但不完全是你的问题。它确实处理父/子 ViewModel 对象之间的属性通信。
让我们看一个基本示例:
ViewModelA
是父级,必须呈现 B 上某些属性的总和ViewModelB
是子级,并且有一个需要求和的属性,因此用户发出编辑 B 上的属性的请求并且请求成功,因此 B 可能会更改其属性的值并触发
PropertyChanged
事件。ViewModelA 可以订阅所有子级的事件,但是沿着这条路走下去,我不喜欢它。添加和删除子项时,您需要做大量簿记工作。
将 A 注入 B 更干净,但您仍然需要做很多簿记工作。如果你对A采取“清除儿童”行动怎么办?在任何情况下,你都必须记住正确地摆脱B与A的亲子关系。在我看来,它仍然比事件更好,因为它更明确。
我个人喜欢消息传递的想法。我比 Prism 更熟悉 MVVM Light 的信使,但它们的想法是一样的……全局消息总线。任何时候,任何B都可以说“我改变了我的财产!”然后 A 监听通知并自行进行计算。我认为这是最干净的解决方案,记账工作要少得多。
I suggest you read this question (and my answer) since it's similar, but not exactly your problem. It does deal with communication of properties between parent/child ViewModel objects.
Let's look at a basic example:
ViewModelA
is the parent and has to present the Sum of some property on BViewModelB
is the child and has a property that needs summingSo the user makes a request to edit the property on B and the request succeeds, so B presumably changes the value of its property and fires a
PropertyChanged
event.ViewModelA
could subscribe to the events on all children, but having gone down that path, I don't like it. When children are added and removed, you have a lot of bookkeeping to do.Injecting A into B is cleaner, but you still have a lot of bookkeeping to do. What if you have a "Clear Children" action on A? You have to remember to properly get rid of the parent relationship from B to A in all cases. Still it's better than events in my opinion because it's more explicit.
Personally I like the messaging idea. I'm more familiar with MVVM Light's messenger than Prism, but it's the same idea... a global message bus. At any time, any B can say "I changed my property!" and then A listens for the notification and does the computation itself. I think this is your cleanest solution with much less bookkeeping.
我建议使用更轻量级的专用
Messaging
解决方案,称为“轻消息总线”。它不是任何另一个 ;-) MVVM 框架的一部分,而是独立的组件。我在不到 3 分钟的时间内就让它工作了。I suggest using a much lighter dedicated
Messaging
solution called "Light Message Bus". It is not part of any yet another ;-) MVVM framework, but independent component. And I got it working in no time in less than 3 minutes.您可能会发现 WPF 应用程序框架 (WAF) 的示例应用程序很有用。 ViewModel 彼此不了解。它们之间的中介由控制器完成。这样您就可以防止 ViewModel 对象之间的循环依赖关系。
You might find the sample applications of the WPF Application Framework (WAF) useful. The ViewModels don't know about each other. The mediation between them is done by Controllers. This way you can prevent cyclic dependencies between ViewModel objects.