У меня есть простое приложение, состоящее из:
Модель
- Предметы
- Критерии фильтрации, примененные к этому списку элементов
Просмотры
- Страница приветствия
- ГлавнаяЭлементыСтраница
- ФильтрРедактироватьСтраницу
Я использую MVVM Light и Windows Phone 7.
В настоящее время у меня есть 3 ViewModels, по одному для каждого представления. В прошлом у меня была одна ViewModel, которая делала общение, о котором я собираюсь спросить, очень простым. Однако я хотел использовать 3 отдельные виртуальные машины, поскольку это кажется правильным путем.
Страница приветствия может установить один из критериев фильтра перед переходом на страницу MainItemsPage. MainItemsPage привязан к свойству Items, которое предоставляется его ViewModel. Эта ViewModel должна отфильтровать этот список в зависимости от текущих критериев фильтрации. Страница FilterEditPage позволяет пользователю редактировать полный набор критериев из 4 переменных. Когда критерии изменены, необходимо повторно отфильтровать коллекцию Items, используемую в ViewModel для MainItemsPage.
Вопрос в том, как я пропускаю изменения фильтра через приложение. Я знаю, что в MVVM есть концепция обмена сообщениями, а инструментарий MVVM Light предоставляет класс Messenger. Однако то, с чем я борюсь, заключается в том, где лежит ответственность за отправку этих сообщений?
- Переходят ли 3 виртуальные машины к модели всякий раз, когда им нужно работать с текущим набором фильтров?
- Проходят ли все обновления фильтра через модель FilterEditViewModel, которая, в свою очередь, передает сообщение об изменении фильтра?
- Можно ли вернуться к одной виртуальной машине для всех представлений?
Я не вижу, чтобы 1. работало, потому что что-то должно будет вызвать виртуальные машины, чтобы вернуться к модели, которую я знаю, что могу заставить 3. работать прямо сейчас без проблем. Это неправильно?
ТИА
Пэт Лонг
Ответ 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; } }
}
Здесь вы можете получить доступ ко всем моделям просмотра, и это нормально, потому что вы остаетесь на уровне "контроллера".