wpf MVVM中视图模型的交互
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14361687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Interaction of view models in MVVM
提问by Robert Strauch
I have a WPF application which follows the MVVM pattern. The application defines two views and view models so far:
我有一个遵循 MVVM 模式的 WPF 应用程序。到目前为止,该应用程序定义了两个视图和视图模型:
- LoginView(Model)
- ProjectsView(Model)
- 登录视图(模型)
- 项目视图(模型)
Both view models need to access several properties from other view models.
两个视图模型都需要访问其他视图模型的几个属性。
Example:LoginViewModelhas a property ProjectList. ProjectsViewModelneeds to access this property as well.
示例:LoginViewModel有一个属性ProjectList。ProjectsViewModel也需要访问此属性。
This is only a simple example. Later there will be several UserControlswhich all need to interact with each other.
这只是一个简单的例子。稍后将有几个UserControls都需要相互交互。
Would it be a better idea to create one huge view model which all UserControls(views) set as their DataContext? If not, how can all the different view models interact with each other?
创建一个所有UserControls(视图)都设置为它们的巨大视图模型会更好DataContext吗?如果没有,所有不同的视图模型如何相互交互?
Remark:
This question is closely related to this onebut with a different approach.
备注:
这个问题是密切相关的这一个,但有不同的方法。
回答by Jon
You should definitely not make a huge "main view model" -- this is an anti-pattern not dissimilar to a god object.
你绝对不应该制作一个巨大的“主视图模型”——这是一个与上帝对象没有什么不同的反模式。
The key idea here is that your viewmodels do not need to access several properties from other view models; rather, all of the viewmodels need to access specific pieces of information.
这里的关键思想是您的视图模型不需要从其他视图模型访问多个属性;相反,所有的视图模型都需要访问特定的信息。
Right now you are most likely injecting this information into each viewmodel at the time of instantiation. Instead of doing this, provide each viewmodel with a reference to a service-- an application module that exposes this information through properties and/or methods. The information can be exposed in the form of scalar values if it's extremely simple in nature, or in the form of models if it's anything more complicated than that.
现在,您很可能在实例化时将此信息注入每个视图模型。不是这样做,而是为每个视图模型提供对服务的引用——一个通过属性和/或方法公开此信息的应用程序模块。如果信息本质上非常简单,则可以以标量值的形式公开;如果比这更复杂,则可以以模型的形式公开。
Schematically this would look like
示意性地这看起来像
/--------------\
| ViewModelA |
| | <=======\
| | |
\--------------/ | <--- information is pulled /================\
+=========[model]===[model]====== | Service |
/--------------\ | \================/
| ViewModelB | |
| | <=======/
| |
\--------------/
The service should be injectedinto the viewmodels upon construction (either manually or by the DI container if you are using one). Each viewmodel should only require a reference to the service and enough information to tell to the service which model it's interested in; it will then request that model from the service and populate its "interesting" properties based on that.
该服务应该在构建时注入到视图模型中(手动或通过 DI 容器,如果您正在使用)。每个视图模型应该只需要对服务的引用和足够的信息来告诉服务它对哪个模型感兴趣;然后它将从服务请求该模型并基于此填充其“有趣的”属性。
This way of doing things is more involved than simply constructing a viewmodel object and setting its properties externally, but it will allow your application to grow in complexity without becoming unmanageable.
这种做事方式比简单地构造一个视图模型对象并在外部设置其属性更复杂,但它会使您的应用程序变得越来越复杂,而不会变得难以管理。
For example, if there are lots of views that bind on different viewmodels and these viewmodels depend in complex ways on a number of models, a sane manner to work would be:
例如,如果有很多视图绑定在不同的视图模型上,并且这些视图模型以复杂的方式依赖于许多模型,那么合理的工作方式是:
- A view/viewmodel pair is constructed
- The viewmodel requests any models it needs to know about from the service; it subscribes to an event that the service exposes to let subscribers know that a model has changed
- Changes are performed to the models through databound controls
- The view invokes a "save" command on the viewmodel
- In response to that, the viewmodel invokes a "save this model" method on the service
- The service persists the information and publishes a "model changed" event (see step 2)
- Other viewmodels interested in the same model know that the model has changed and can query the service for its new state
- 构建了一个视图/视图模型对
- 视图模型从服务请求它需要知道的任何模型;它订阅服务公开的事件,让订阅者知道模型已更改
- 通过数据绑定控件对模型执行更改
- 视图调用视图模型上的“保存”命令
- 作为响应,视图模型调用服务上的“保存此模型”方法
- 该服务保留信息并发布“模型更改”事件(请参阅步骤 2)
- 对同一模型感兴趣的其他视图模型知道模型已更改并且可以查询服务以获取其新状态
This is possible if everything is routed through the service. Imagine what it would take to keep everything synchronized otherwise -- the only way to cope would be to put all the information into a giant viewmodel and reference that from everything else. Ugly.
如果一切都通过服务路由,这是可能的。想象一下,否则要保持所有内容同步需要什么——唯一的应对方法是将所有信息放入一个巨大的视图模型中,并从其他所有内容中引用它。丑陋的。
回答by Rachel
Usually I do one of 4 things:
通常我会做以下四件事之一:
Make my ViewModels reference each other, and pass the property around. For example,
LoginViewModelmight setProjectsViewModel.ProjectListon successful login. How you implement this depends on how your ViewModels are related to each other, and where logical points of connection would be.Make an
ApplicationViewModelwhich manages things like which page is current, and application-wide objects like the current user or current project list. It would handle transferring shared data to the ViewModels that needs it.Use some kind of Event system to broadcast a message anytime an application-wide property changes, and have any ViewModel that's interested subscribe to receive those messages. The message typically contains the new object as well, so anyone subscribed to receive that message type has access to the new object. (I have a brief summary of Event Systems in my blog article Communication between ViewModels with MVVMif you're interested)
Depending on if any of the other options work better, I may consider creating a singleton to hold application-wide data instead. For example, if the User is set on Login and is accessed from many of my ViewModels, I may create a singleton to set the user on first login, and then all my ViewModels can access it.
让我的 ViewModel 相互引用,并传递属性。例如,
LoginViewModel可能设置ProjectsViewModel.ProjectList成功登录。您如何实现这一点取决于您的 ViewModel 如何相互关联,以及连接的逻辑点在哪里。创建一个
ApplicationViewModel管理诸如当前页面之类的内容,以及当前用户或当前项目列表等应用程序范围的对象。它将处理将共享数据传输到需要它的 ViewModel。使用某种事件系统在应用程序范围的属性更改时随时广播消息,并让任何感兴趣的 ViewModel 订阅接收这些消息。该消息通常也包含新对象,因此订阅接收该消息类型的任何人都可以访问新对象。(如果您有兴趣,我在我的博客文章“ ViewModels 与 MVVM 之间的通信”中对事件系统进行了简要总结)
根据是否有任何其他选项效果更好,我可能会考虑创建一个单例来保存应用程序范围的数据。例如,如果用户在登录时设置并从我的许多 ViewModel 访问,我可能会创建一个单例来在第一次登录时设置用户,然后我的所有 ViewModel 都可以访问它。
The one thing I would notdo is make one big ViewModel holding all available data. ViewModels should only contain the data specific to it.
我不会做的一件事是制作一个包含所有可用数据的大 ViewModel。ViewModels 应该只包含特定于它的数据。
回答by Bhauraj Biradar
Create one Base View Model keep all common Properties in that, Create singleton to BaseViewModel and add that singleton property in all View Models. All Viewmodels will get synced at one time.
创建一个基本视图模型,保留所有公共属性,创建单例到 BaseViewModel 并在所有视图模型中添加该单例属性。所有 Viewmodels 将一次同步。
回答by Josh
If you are using some sort of dependency injection tooling, you could inject a class that provides those values, for example, an IProjectService, that can return the list of projects on each of those view models.
如果您正在使用某种依赖注入工具,您可以注入一个提供这些值的类,例如,一个 IProjectService,它可以返回每个视图模型上的项目列表。
The idea of one giant view model does not sound appealing, nor does strong coupling between view models by accessing each other's public properties. And if you want interaction between the view models, like when a project gets added, use a publish / subscribe model for each of the events you expect to occur.
一个巨大的视图模型的想法听起来并不吸引人,视图模型之间通过访问彼此的公共属性的强耦合也没有吸引力。如果您希望视图模型之间进行交互,例如添加项目时,请为您期望发生的每个事件使用发布/订阅模型。
回答by JDB still remembers Monica
Your Model should contain things like a project list, or give you the ability to access it. The ViewModel is simply meant to be a layer between the Model and View, giving you the chance to bring different Model objects together and mold them into a shape which the View can readily display and to handle commands from the View (modifying the Model in response).
您的模型应该包含诸如项目列表之类的内容,或者让您能够访问它。ViewModel 只是作为 Model 和 View 之间的一个层,让您有机会将不同的 Model 对象组合在一起,并将它们塑造成 View 可以轻松显示的形状,并处理来自 View 的命令(修改模型以响应)。

