MVVM:模型和视图模型之间的通信

发布于 2024-10-02 19:22:58 字数 610 浏览 0 评论 0原文

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

我读过很多博客文章,但我对让我的班级相互交流的“正确”方式感到非常困惑。特别是,我不知道什么时候使用依赖注入,什么时候依赖中介模式。

让我们考虑一个例子。我有一个 ViewModel,我们称之为 DataViewModel,以及提供某种数据的 Data 类。 如何更好地在它们之间进行通信:

A. 使用 IData 接口向 DataViewModel 注入依赖项?这样,Data 就不必依赖 Messenger,但如果 Data 发生变化,它必须提供一个事件,并且 ViewModel 必须订阅该事件。

B. 依赖中介者模式(在 MVVM Light 中实现为 Messenger)并在 Model 和 ViewModel 之间发送消息?这样就根本不需要使用依赖注入,因为整个通信将基于消息。

此外,我的 ViewModel 是否应该注入对其他 ViewModel 的依赖项,或者仅仅依赖 Messenger 会更好?如果是第一种,是否有必要为每个 ViewModel 定义一个单独的接口?我认为为每个虚拟机定义一个接口将是一项额外的工作,但也许这是值得的。

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.

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. 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. 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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雾里花 2024-10-09 19:22:58

通常,ViewModel 会转到服务(Prism 称之为服务)来检索所需的数据。该服务通过 DI(构造函数注入)推送到 ViewModel,尽管您可以通过 ServiceLocator 以另一种方式执行此操作。

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

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

        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;
           }
       }

当你进入视图时,同样的情况也会发生,视图将通过 DI(构造函数注入)与 ViewModel 一起注入。我不会让其他 ViewModel 相互依赖,让它们保持隔离。如果您开始发现需要耦合,请查看您尝试共享的数据,通常情况下,该数据需要进一步抽象,而不是耦合到任何 ViewModel。

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.

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.

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;
           }
       }

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.

ぶ宁プ宁ぶ 2024-10-09 19:22:58

对于您的问题,有不止一种好的解决方案,

我建议您在数据模型中使用一些单一接口,将其放在基类中,该接口将允许您的数据对象与外界进行通信。

对于视图模型来说,注入的不是数据,而是一个可以为您检索数据的接口,数据将公开虚拟机在获取数据后可以向它们注册的事件。

数据对象不应该知道谁拥有他,视图模型知道他拥有什么样的数据,但由于灵活性问题,我不建议注入这些数据。

There is more than one good solution to your problem,

I suggest you to use some single interface in your data models, put it in a base class, this interface will allow your data objects to communicate with the outside world.

For the view models inject not the data but an interface that can retrieve data for you, the data will expose events that the vm can register to them after he gets them.

data oject should not know who holds him, view model knows what kind of data he holds but I dont recommend to inject this data due to flexibility issues.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文