Что такое ViewModelLocator и каковы его плюсы и минусы по сравнению с DataTemplates?

Вопрос:Может кто-нибудь дать мне краткое описание того, что такое ViewModelLocator, как он работает и какие плюсы/минусы для его использования по сравнению с DataTemplates? Я пробовал находить информацию о Google, но, похоже, это много разных реализаций, и ни один из списков stryaght относительно того, что это такое, и плюсы/минусы использования. Лучший ответ: Введение В MVVM обычная

Вопрос:

Может кто-нибудь дать мне краткое описание того, что такое ViewModelLocator, как он работает и какие плюсы/минусы для его использования по сравнению с DataTemplates?

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

Лучший ответ:Содержание

  1. Введение
  2. Преимущества DI
  3. Проблемы, связанные с DI
  4. Введите ViewModelLocator
  5. Резюме

Введение

В MVVM обычная практика заключается в том, чтобы представления находили свои ViewModels, разрешая их из контейнера dependication injection (DI). Это происходит автоматически, когда контейнеру предлагается предоставить (разрешить) экземпляр класса View. Контейнер вставляет ViewModel в представление, вызывая конструктор представления, который принимает параметр ViewModel; эта схема называется инверсией управления (IoC).

Преимущества DI

Основное преимущество здесь заключается в том, что контейнер можно настроить во время выполнения с инструкциями о том, как разрешать типы, которые мы запрашиваем от него. Это позволяет повысить степень проверки, инструктируя его разрешать типы (Views и ViewModels), которые мы используем, когда наше приложение действительно выполняется, но инструктируя его по-разному при выполнении модульных тестов для приложения. В последнем случае приложение даже не будет иметь пользовательский интерфейс (он не работает, просто тесты), поэтому контейнер разрешит mocks вместо “обычные” типы, используемые при запуске приложения.

Проблемы, связанные с DI

До сих пор мы видели, что подход DI позволяет легко тестировать приложение, добавляя слой абстракции над созданием компонентов приложения. Существует одна проблема с этим подходом: он плохо работает с визуальными дизайнерами, такими как Microsoft Expression Blend.

Проблема заключается в том, что при запуске обычных приложений и unit test кто-то должен настроить контейнер с инструкциями о том, какие типы должны быть разрешены; Кроме того, кто-то должен попросить контейнер разрешить представления, чтобы в них можно было вставлять ViewModels.

Однако во время разработки кода не работает наш код. Дизайнер пытается использовать отражение для создания экземпляров наших представлений, что означает, что:

  • Если конструктору вида требуется экземпляр ViewModel, конструктор не сможет создать экземпляр представления вообще – он будет некорректно выходить из строя.
  • Если View имеет конструктор без параметров, будет создан экземпляр View, но его DataContext будет null, поэтому мы получим “пустой” вид в дизайнере, что не очень полезно

Введите ViewModelLocator

ViewModelLocator – это дополнительная абстракция, используемая следующим образом:

  • Сам вид создает экземпляр ViewModelLocator как часть его ресурсов и привязывает его DataContext к свойству ViewModel локатора
  • Локатор каким-то образом обнаруживает, находятся ли мы в режиме разработки
  • Если нет в режиме разработки, локатор возвращает ViewModel, который он разрешает из контейнера DI, как описано выше.
  • Если в режиме разработки локатор возвращает фиксированный “dummy” ViewModel, используя свою собственную логику (помните: во время разработки нет контейнера!); этот ViewModel обычно заносится в фиктивные данные

Конечно, это означает, что для представления View должен иметь конструктор без параметров (в противном случае конструктор не сможет его создать).

Резюме

ViewModelLocator – это идиома, которая позволяет вам сохранять преимущества DI в вашем приложении MVVM, а также позволяя вашему коду хорошо играть с визуальными дизайнерами. Иногда это называется “смешиваемостью” вашего приложения (ссылка на выражение).

После переваривания выше см. практический пример здесь.

Наконец, использование шаблонов данных не является альтернативой использованию ViewModelLocator, а является альтернативой использованию явных пар View/ViewModel для частей вашего пользовательского интерфейса. Часто вы можете обнаружить, что нет необходимости определять представление для ViewModel, потому что вместо этого вы можете использовать шаблон данных.

Ответ №1

Пример реализации @Jon answer

У меня есть класс локатора модели представления. Каждое свойство будет экземпляром модели представления, которую я собираюсь выделить на моем представлении. Я могу проверить, работает ли код в режиме разработки или не используется DesignerProperties.GetIsInDesignMode. Это позволяет мне использовать макет модели во время проектирования и реального объекта, когда я запускаю приложение.

public class ViewModelLocator { private DependencyObject dummy = new DependencyObject(); public IMainViewModel MainViewModel { get { if (IsInDesignMode()) { return new MockMainViewModel(); } return MyIoC.Container.GetExportedValue<IMainViewModel>(); } } // returns true if editing .xaml file in VS for example private bool IsInDesignMode() { return DesignerProperties.GetIsInDesignMode(dummy); } }

И чтобы использовать его, я могу добавить свой локатор в App.xaml ресурсы:

xmlns:core=»clr-namespace:MyViewModelLocatorNamespace» <Application.Resources> <core:ViewModelLocator x:Key=»ViewModelLocator» /> </Application.Resources>

И затем подключите свой вид (например: MainView.xaml) к вашей модели просмотра:

<Window … DataContext=»{Binding Path=MainViewModel, Source={StaticResource ViewModelLocator}}»> Ответ №2

Я не понимаю, почему другие ответы этого вопроса обернутся вокруг Дизайнера.

Цель View Model Locator – позволить вашему представлению создать экземпляр (да, View Model Locator = View First):

public void MyWindowViewModel(IService someService) { }

вместо этого:

public void MyWindowViewModel() { }

объявив это:

DataContext=»{Binding MainWindowModel, Source={StaticResource ViewModelLocator}}»

Где ViewModelLocator – класс, который ссылается на IoC и что он решает свойство MainWindowModel, которое он предоставляет.

Это не имеет никакого отношения к предоставлению моделей Mock для просмотра. Если вы этого хотите, просто

d:DataContext=»{d:DesignInstance MockViewModels:MockMainWindowModel, IsDesignTimeCreatable=True}»

Локатор View Model является оболочкой вокруг некоторого (любого) Inversion of Control контейнера, например Unity.

Обратитесь к:

Оцените статью
Добавить комментарий