Подтвердить что ты не робот

ViewModels в ViewModelLocator MVVM Light

Правильно ли хранить все мои ViewModels в SimpleIoc? Например, у меня есть три страницы MainPage, Photos, Directories (поэтому три ViewModels → MainVM, PhotosVM, DirectoriesVM). Должен ли я установить DataContext на каждой странице, чтобы просмотреть свойство модели в ViewModelLocator или вложить ViewModels в качестве свойств в MainVM и привязать каждую страницу DataContext к Main.PhotosVMProperty, Main.DirectoriesVMProperty и т.д.? Может ли кто-нибудь объяснить мне идею и цель IoC?

4b9b3361

Ответ 1

Сначала давайте посмотрим, что делает ViewModelLocator и почему мы его используем:

ViewModelLocator объявлен как объект на нашей странице App.xaml и является одноименным приложением. У нас будет один, и только один из них будет доступен для приложения, когда он будет работать.

ViewModelLocator является источником всех наших ViewModels в MVVM Light. Для каждого ViewModel у нас будет свойство в ViewModelLocator, которое позволяет нам получить ViewModel для представления. Этот код выглядит следующим образом:

public class ViewModelLocator
{
    public MainPageViewModel MainPage
    {
        get { return new MainPageViewModel(); }
    }
}

Это часть моего App.xaml:

<Application.Resources>
    <vm:ViewModelLocator
        x:Key="ViewModelLocator" />
</Application.Resources>

Это часть из View.xaml

DataContext="{Binding MainPage, Source={StaticResource ViewModelLocator}}"

Пока все хорошо. Чтобы ответить на ваш первый вопрос, вам нужно использовать Ioc в MVVM Light? Нет. Нет необходимости в том, чтобы ваша viewmodel была предоставлена ​​вашему представлению, полностью созданному и создаваемому ViewModelLocator.

Теперь, на ваш второй вопрос: Какова цель IoC?

IoC предназначен для того, чтобы вы могли сделать следующее:

С Mvvm Light вы делаете следующее:

public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
        }
        else
        {
            SimpleIoc.Default.Register<IDataService, DataService>();         
        }

        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel Main
    {
        get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
    }
}

public class MainViewModel
{
    public ObservableCollection<Foo> Foos { get; set; }

    public MainViewModel(IDataService dataService)
    {
        _dataService=dataService;
        Foos=_dataService.GetFoos();
    }
}

Когда я разрешаю свой MainViewModel при вызове

SimpleIoc.Default.GetInstance<MainViewModel>()

что происходит внутри, так это то, что SimpleIoc проверяет, имеет ли MainViewModel какие-либо зависимости (параметры в его конструкторе). Затем он пытается решить эти параметры, посмотрев на интерфейсы, которые были зарегистрированы с ним. Он делает это рекурсивно, поэтому, если у DataService была зависимость, он будет создан и передан конструктору DataService при его создании.

Зачем мне все это делать?

  • Сделайте ваши классы легко проверяемыми единицами.
  • Сделайте свой код управляемым интерфейсом. Это означает, что вы ссылаетесь на интерфейсы, а не на конкретные классы
  • Сделайте ваш код свободно связанным. Это означает, что кто-то может изменить реализацию интерфейса и классов, которые потребляют этот интерфейс, не заботятся и не нуждаются в повторной кодировке.
  • Автоматически разрешать зависимости классов.
  • В MVVM Light вы увидите, что он может определить, когда он работает в режиме разработки (ViewModelBase.IsInDesignModeStatic), это означает, что вы можете создавать службы времени разработки для предоставления данных в виде viewmodels, чтобы ваш View в Visual Studio содержал фактические данные.

Ответ 2

MVVM Light имеет много приятных функций, но мне кажется, что Locator службы создает нежелательную зависимость просмотров на моделях просмотра. В идеале я хотел бы иметь ViewModelLocator в Библиотеке A, модели представления в Библиотеке B и представлениях в Библиотеке C. Затем я могу смешивать и сопоставлять их по мере необходимости для будущих проектов. Тем не менее, в дизайне MVVM Light, насколько я вижу, представления (библиотека C) всегда будут иметь зависимость от ViewModelLocator (это нормально), но поскольку ViewModelLocator (Библиотека A) всегда будет иметь зависимость от (библиотека B), то представления всегда будут зависеть от моделей представления (это не нормально, потому что представление теперь должно включать все библиотеки моделей представлений, которые когда-либо использовались для всех продуктов).

Я считаю, что Призма обходит эту проблему, используя как-то строковые ключи. Я что-то пропустил?

Oops! Кажется, я просто ответил на свой вопрос. Решение состоит в том, чтобы сделать библиотеку A, ServiceLocator, специфичной для конкретного решения (продукта). Затем он содержит ссылку на модели просмотра только для этого решения. Тогда взгляды зависят от этого ServiceLocator, который, в свою очередь, зависит от всех моделей просмотров для этого продукта. Конечным результатом является то, что представления зависят только от моделей представлений, которые будут использоваться для этого продукта. Нет никакой проблемы с тем фактом, что мы дублируем ServiceLocator для каждого решения, потому что этот модуль содержит только код, специфичный для решения. Компоненты ServiceLocator, такие как класс SimpleIoc, являются, конечно, общими для всех решений, но они были учтены в повторно используемых классах, которые мы вызываем в ServiceLocator.

Подводя итог, проблема, которую я пытаюсь решить, предполагает, что решение имеет 6 моделей взглядов, четыре из которых тесно связаны друг с другом, а два из них тесно связаны. Поэтому мы создаем две сборки, каждая из которых содержит тесно связанные модели представлений. Предположим, мы разработали продукт, который использует один набор моделей представлений, и решение предназначено для запуска Windows 8. Теперь все представления разные, и мы хотим повторно использовать только один набор (сборку) моделей просмотра. Поэтому мы просто создаем новую сборку ServiceLocator, которая указывает на эту сборку моделей просмотра, а также любые другие, которые нам нужны. Наши новые представления Windows 8 теперь зависят от этой новой сборки ServiceLocator и только моделей представлений, которые используются в нашем новом продукте (решении).