MVVM:Model和ViewModels之间的通信

mad*_*ger 6 wpf dependency-injection mediator mvvm-light

我正在使用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定义一个单独的接口?我认为为每个VM定义一个接口将是一项额外的工作,但也许值得.

Aar*_*ver 4

通常,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;
           }
       }
Run Code Online (Sandbox Code Playgroud)

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