Bezdepbonusu7Программирование: статьи и ответы

Вопрос

MVVM - определение того, какая ViewModel за что отвечает

Автор вопроса: Pat Long - Munkii YebeeОтветов: 2

У меня есть простое приложение, состоящее из:

Модель

  • Предметы
  • Критерии фильтрации, примененные к этому списку элементов

Просмотры

  • Страница приветствия
  • ГлавнаяЭлементыСтраница
  • ФильтрРедактироватьСтраницу

Я использую MVVM Light и Windows Phone 7.

В настоящее время у меня есть 3 ViewModels, по одному для каждого представления. В прошлом у меня была одна ViewModel, которая делала общение, о котором я собираюсь спросить, очень простым. Однако я хотел использовать 3 отдельные виртуальные машины, поскольку это кажется правильным путем.

Страница приветствия может установить один из критериев фильтра перед переходом на страницу MainItemsPage. MainItemsPage привязан к свойству Items, которое предоставляется его ViewModel. Эта ViewModel должна отфильтровать этот список в зависимости от текущих критериев фильтрации. Страница FilterEditPage позволяет пользователю редактировать полный набор критериев из 4 переменных. Когда критерии изменены, необходимо повторно отфильтровать коллекцию Items, используемую в ViewModel для MainItemsPage.

Вопрос в том, как я пропускаю изменения фильтра через приложение. Я знаю, что в MVVM есть концепция обмена сообщениями, а инструментарий MVVM Light предоставляет класс Messenger. Однако то, с чем я борюсь, заключается в том, где лежит ответственность за отправку этих сообщений?

  1. Переходят ли 3 виртуальные машины к модели всякий раз, когда им нужно работать с текущим набором фильтров?
  2. Проходят ли все обновления фильтра через модель FilterEditViewModel, которая, в свою очередь, передает сообщение об изменении фильтра?
  3. Можно ли вернуться к одной виртуальной машине для всех представлений?

Я не вижу, чтобы 1. работало, потому что что-то должно будет вызвать виртуальные машины, чтобы вернуться к модели, которую я знаю, что могу заставить 3. работать прямо сейчас без проблем. Это неправильно?

ТИА

Пэт Лонг

mvvmmvvm-light

Ответы

Ответ 1 · LittleColin

Я бы поместил общий текущий фильтр в модель, а не в модель представления. У вас есть много viewModel потенциально на разных страницах или на одной странице (рассмотрите навигационную цепочку, показывающую текущий выбор, и что-то еще, что должно показать, что фильтр был применен).

Как насчет одноэлементной модели для фильтра, на которую могут подписаться модели представлений?

Ответ 2 · JanW

Три виртуальные машины - правильный путь в вашем сценарии. Я предлагаю вам построить отношения "родитель-потомок" между вашими виртуальными машинами. Поскольку MainVM содержит ItemList, это место, где применяются FilterChanges. FilterEditVM только получает изменения фильтра, а затем вызывает MainVM, который должен повторно применить фильтры.

Структура будет примерно такой:

public class WelcomePageVM
{
    public WelcomePageVM()
    {
        this.FilterEditPageVM = new FilterEditPageVM(this);
        this.MainItemsVM = new MainItemsVM(this);
    }

    public FilterEditPageVM FilterEditPageVM { get; private set; }

    public MainItemsVM MainItemsVM { get; private set; }

    public void SetInitialFilter1(object filter)
    {
        // the initial filter
        this.FilterEditPageVM.Filter1Value = filter;
        this.MainItemsVM.ApplyFilters();
    }
}

public class FilterEditPageVM : ChildViewModelBase<WelcomePageVM>
{
    public FilterEditPageVM(WelcomePageVM parent)
        : base(parent) { }

    public object Filter1Value { get; set; }
    public object Filter2Value { get; set; }
    public object Filter3Value { get; set; }
    public object Filter4Value { get; set; }

    public void FinishFilterChange()
    {
        this.Parent.MainItemsVM.ApplyFilters();
    }
}

public class MainItemsVM : ChildViewModelBase<WelcomePageVM>
{
    public MainItemsVM(WelcomePageVM parent)
        : base(parent) { }

    public List<object> ItemList { get; set; }

    public void ApplyFilters()
    {
        // filter apply logic
    }
}

public abstract class ChildViewModelBase<T>
{
    T _parent;

    public ChildViewModelBase(T parent)
    {
        this._parent = parent;
    }

    public T Parent { get { return _parent; } }
}

Здесь вы можете получить доступ ко всем моделям просмотра, и это нормально, потому что вы остаетесь на уровне "контроллера".

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы