MVVM:模型与ViewModel之间的通信 [英] MVVM: Communication between the Model and ViewModels

查看:925
本文介绍了MVVM:模型与ViewModel之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MVVM模式开发WPF应用程序.我正在使用MVVM Light库,并且还尝试使用依赖项注入器(我正在考虑Ninject和Unity).

I'm developing a WPF application using the MVVM pattern. I'm using MVVM Light library and I'm also trying to use a dependency injector (I'm considering Ninject and Unity).

我已经阅读了很多博客文章,并且对使类彼此进行交流的正确"方法感到非常困惑.特别是,我不知道何时使用依赖注入以及何时依赖中介模式.

I've read a lot of blog articles and I'm quite confused about the "proper" way of making my classes communicate with each other. In particular, I don't know when to use Dependency Injection and when to rely on the mediator pattern.

让我们考虑一个例子.我有一个ViewModel,可以称之为DataViewModel,而Data类则提供某种数据. 他们之间如何沟通更好?

Lets consider an example. I have a ViewModel, lets call it DataViewModel, and the Data class that provides some kind of data. How is it better to communicate between them:

A.使用IData接口将依赖项注入DataViewModel吗?这样,数据就不必依赖Messenger了,但是如果数据发生变化,它就必须提供一个事件,而ViewModel必须订阅它.

A. Inject a dependency to DataViewModel with an interface of IData? This way Data will not have to rely on Messenger, but it will have to provide an event if the Data changes, and the ViewModel will have to subscribe to it.

B.依靠中介模式(在MVVM Light中作为Messenger实现)并在Model和ViewModel之间发送消息?通过这种方式,完全不需要使用依赖注入,因为整个通信将基于消息.

B. Rely on the mediator pattern (implemented in MVVM Light as Messenger) and send messages between Model and ViewModel? This way it will not be necessary to use Dependency Injection at all, because whole communication will be based on messages.

此外,我的ViewModel是否应该注入对其他ViewModel的依赖关系,还是最好依靠Messenger?如果是第一个,是否有必要为每个ViewModel定义一个单独的接口?我认为为每个VM定义接口将是一项额外的工作,但这也许是值得的.

Moreover, should my ViewModels have injected dependencies on other ViewModels, or it would be better just to rely on the Messenger? If the first, would it be necessary to define a separate interface for each ViewModel? I think that defining an interface for each VM will be an additional work, but maybe it is worth it.

推荐答案

通常,ViewModel转到服务(如Prism所称)以检索所需的数据.该服务通过DI(构造函数注入)被推送到ViewModel,尽管您可以通过ServiceLocator执行另一种方式.

Generally the ViewModel goes to a Service (as Prism calls it) to retrieve the data it needs. That service is pushed to the ViewModel via DI (Constructor Injection) although you could perform this another way via a ServiceLocator.

因此,您的ViewModel将保存对服务的引用,该服务将抽象化数据的检索.数据可能来自DB,XML文件,谁知道...抽象就在那里.因此,对于您的IData而言,对该类型的引用将在ViewModel中的某个点发生,但不会通过DI中的任何方式发生.如果您的IoC框架允许(Prism允许),则可以创建接口类型到具体类型的映射,然后通过容器检索这些类型. Unity就是这种情况.

Therefore your ViewModel will hold a reference to a service which will abstract away the retrieval of your data. The data could be coming from a DB, XML file, who knows...the abstraction is there. So for your case of IData, the reference to that type will occur at some point in the ViewModel but not by way of any from of DI. If your IoC framework allows it (Prism does) you create mappings of interface types to concrete types and then retrieve those types via your container; such is the case with Unity.

这是一个简短的示例...将脚本绑定到View,并将ViewModel注入到View中.注意使用IScriptService检索数据.返回的数据是IScript类型的集合,但是我们从未将类型正式注入到ViewModel中,因为我们不关心类型是单个实体,而是关心宏大的类型.

Here is a brief example...Scripts is bound to the View and the ViewModel is injected into the View. Notice the use of the IScriptService to retrieve the data. The data coming back is a collection of IScript types, however we never formally injected that type into the ViewModel because we don't care about the type as a single entity we care about the type on a grandeur scale.

        public ScriptRepositoryViewModel(IUnityContainer container, IScriptService scriptService, IEventAggregator eventAggregator)
        {
            _container = container;
            _scriptService = scriptService;
            _eventAggregator = eventAggregator;
        }

        public ICollectionView Scripts
        {
           get 
           {
               if (_view == null)
               {
                   _view = CollectionViewSource.GetDefaultView(_scriptService.Scripts);
                   _view.Filter = Filter;
               }

               return _view;
           }
       }

当您进入View时,可能会遇到相同的情况,该View将通过使用ViewModel的DI(构造函数注入)注入.我不会让其他ViewModel相互依赖,保持隔离.如果您开始发现需要耦合,请查看您尝试共享的数据,这时通常需要对该数据进行进一步的抽象,并且不与任何ViewModel耦合.

When you make your way to the View, the same case can be had there, the View will get injected via DI (Constructor Injection) with the ViewModel. I would not make other ViewModels depend on each other, keep them isolated. If you begin to see a need for coupling take a look at the data you are trying to share, more often then to that data needs to be abstracted out further and not become coupled to any ViewModel.

这篇关于MVVM:模型与ViewModel之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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