MVVM: связь между моделью и моделями представления - PullRequest
6 голосов
/ 17 ноября 2010

Я разрабатываю приложение WPF с использованием шаблона MVVM. Я использую библиотеку MVVM Light и пытаюсь использовать инжектор зависимостей (я рассматриваю Ninject и Unity).

Я прочитал много статей в блогах, и я весьма озадачен «правильным» способом заставить мои классы общаться друг с другом. В частности, я не знаю, когда использовать инъекцию зависимости, а когда полагаться на шаблон посредника.

Давайте рассмотрим пример. У меня есть ViewModel, давайте назовем его DataViewModel и класс Data, который предоставляет какие-то данные. Как лучше общаться между ними:

A. Внедрить зависимость от DataViewModel с интерфейсом IData? Таким образом, Данные не должны будут полагаться на Messenger, но должны будут предоставить событие, если Данные изменятся, и ViewModel придется подписаться на него.

B. Положитесь на шаблон посредника (реализованный в MVVM Light as Messenger) и отправляйте сообщения между Model и ViewModel? Таким образом, совсем не обязательно будет использовать Dependency Injection, потому что все общение будет основано на сообщениях.

Кроме того, должны ли мои ViewModel вводить зависимости от других ViewModels, или было бы лучше просто положиться на Messenger? Если первое, будет ли необходимо определять отдельный интерфейс для каждой ViewModel? Я думаю, что определение интерфейса для каждой виртуальной машины будет дополнительной работой, но, возможно, оно того стоит.

Ответы [ 2 ]

4 голосов
/ 17 ноября 2010

Обычно ViewModel обращается к Сервису (как его называет Prism), чтобы получить необходимые данные.Этот сервис передается в ViewModel через DI (Constructor Injection), хотя вы можете выполнить это другим способом через ServiceLocator.

Поэтому ваша ViewModel будет содержать ссылку на сервис, который будет абстрагироваться от получения ваших данных.Данные могут поступать из БД, файла XML, который знает ... абстракция есть.Так что для вашего случая IData ссылка на этот тип будет происходить в какой-то момент в ViewModel, но не через какой-либо из DI.Если ваша инфраструктура IoC позволяет это (Prism делает это), вы создаете сопоставления типов интерфейсов с конкретными типами, а затем извлекаете эти типы через ваш контейнер;Так обстоит дело с Unity.

Вот краткий пример ... Сценарии привязываются к представлению, а модель представления внедряется в представление.Обратите внимание на использование 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;
           }
       }

Когда вы доберетесь до View, там может быть тот же случай, View будет внедрен через DI (Constructor Injection) с ViewModel.Я бы не заставлял другие ViewModel зависеть друг от друга, держал бы их изолированными.Если вы начинаете видеть необходимость в связывании, взгляните на данные, которыми вы пытаетесь поделиться, чаще всего эти данные необходимо дополнительно абстрагировать и не привязывать к какой-либо модели представления.

1 голос
/ 17 ноября 2010

Существует более одного хорошего решения вашей проблемы,

Я предлагаю вам использовать какой-то один интерфейс в ваших моделях данных, поместить его в базовый класс, этот интерфейс позволит вашим объектам данных взаимодействовать свнешний мир.

Поскольку модели представлений вводят не данные, а интерфейс, который может извлекать данные для вас, данные будут представлять события, которые виртуальный компьютер может зарегистрировать для них после того, как он их получит.

объект данных долженНе знаю, кто его держит, модель представления знает, какие данные он хранит, но я не рекомендую вводить эти данные из-за проблем с гибкостью.

...