Как поделиться несколькими ObservableCollections с несколькими ViewModels?
Я пишу программу с 4 представлениями: CompanyView, MembersView, WeeksView и ReportsView. У каждого есть соответствующие ViewModel и Model. Я использовал PRISM BindableBase для создания ViewModels. Данные связываются правильно.
- CompanyViewModel содержит объект типа Company.
- MembersViewModel содержит ObservableCollection объектов- членов.
- WeeksViewModel содержит ObservableCollection объектов недели.
Навигация осуществляется с помощью верхних кнопок в главном окне, причем любой вид можно выбрать в любое время.
Container.RegisterTypeForNavigation<CompanyView>("CompanyView");
Container.RegisterTypeForNavigation<MembersView>("MembersView");
Container.RegisterTypeForNavigation<WeeksView>("WeeksView");
Container.RegisterTypeForNavigation<ReportsView>("ReportsView");
Проблема в том, что WeeksViewModel также должен иметь доступ к членам ObservableCollection. И ReportsViewModel также должен иметь доступ к объекту компании, членам ObservableCollection и неделям ObservableCollection.
Я не уверен, как это реализовать. Как я могу легко обмениваться данными между ViewModels?
Я попытался использовать PRISM IEventAggregator для публикации ObservableCollections при их обновлении, и это работает, однако сначала необходимо получить доступ к представлению, прежде чем оно сможет прослушивать событие. Если пользователь ранее не нажимал на представление "Недели", обновленная коллекция MembersCollection не достигнет WeeksView. Могу ли я предварительно инициализировать виды? Как бы я это сделал?
Я следил за MVVM Made Simple с помощью Prism - вебинар ( https://www.youtube.com/watch?v=ZfBy2nfykqY) и обнаружил ту же проблему, написанную в комментариях. Брайан Лагунас предлагает единственный способ исправить это с помощью параметров навигации:
У меня есть небольшая проблема с UpdateEvent, передавая сообщение из ViewAViewModel в ViewBViewModel. Кажется, это не работает, если я не посещал ViewB, я предполагаю, что это потому, что ViewBViewModel еще не был создан до тех пор, пока его представление не было загружено хотя бы один раз.
У кого-нибудь есть какие-либо идеи по этому поводу, я предполагаю, что создание экземпляров всех моделей представления до того, как они понадобятся, является плохой идеей, так как вы можете получить информацию по умолчанию в модель представления из других моделей представления до того, как она будет создана?
Брайан Лагунас: Единственный способ сделать это - передать эту информацию в качестве параметра при переходе к ViewBViewModel.
Я подумал об использовании параметров навигации, но, похоже, вы должны знать, от ГДЕ до ГДЕ вы перемещаетесь. Например, из MembersView > WeeksView передайте коллекцию Members в качестве параметра. Но пользователи могут осуществлять навигацию в любом порядке, в том числе непосредственно в WeeksView при загрузке программы. Например, как WeeksView получает коллекцию участников, если они пришли из представления компании? Компания не знает о Членах коллекции.
Я открыт для других идей, я исследовал повсюду и полностью застрял:-(
Большое спасибо за ваши идеи и помощь! С наилучшими пожеланиями, Дамиан
2 ответа
Проблема в том, что WeeksViewModel также должен иметь доступ к членам ObservableCollection. И ReportsViewModel также должен иметь доступ к объекту компании, членам ObservableCollection и неделям ObservableCollection.
Я не уверен, как это реализовать. Как я могу легко обмениваться данными между ViewModels?
Вы можете использовать одну модель представления со свойствами для каждой конкретной модели представления и общими свойствами, которые будут совместно использоваться двумя или более моделями представления, например:
class MainViewModel
{
public CompanyViewModel CompanyViewModel { get; set; }
public MembersViewModel MembersViewModel { get; set; }
public WeeksViewModel WeeksViewModel { get; set; }
public ObservableCollection<Members> Members { get; set; }
}
Тогда каждое из дочерних представлений может наследовать DataContext
родительского окна и привязать к любому свойству, которое они хотят по всем типам модели представления.
Другим вариантом будет передача информации между моделями представления с использованием прямых ссылок, агрегатора событий или общего сервиса.
Но кажется бессмысленным отчаянно пытаться разделить логику между моделями представления, если они все еще должны иметь доступ к свойствам друг друга. Так что я бы, вероятно, пошел с первым подходом.
Я бы предложил сделать Company
, ObservableCollection<Week>
а также ObservableCollection<Member>
исходить из одной или нескольких услуг.
WeeksViewModel
затем получает ObservableCollection<Week>
а также ObservableCollection<Member>
от службы (ий) и обрабатывает данные для потребления WeeksView
, ReportsViewModel
процессы Company
, ObservableCollection<Week>
а также ObservableCollection<Member>
для потребления ReportsView
... Если кто-то добавляет Member
он делает это через службу, обладающую ObservableCollection<Member>
и все модели просмотра, которые получили ObservableCollection<Member>
от этого сервиса, получит уведомление и обновится соответственно.
Нет необходимости передавать данные между моделями представления, потому что модели представления не владеют данными. Все, что они когда-либо делают, - это преобразовывают данные из какого-либо источника данных для отображения, а наоборот - преобразуют действия пользователя в вызовы службы, которая модифицирует данные.
В тот момент, когда вы просматриваете модели с собственными данными, вы получаете такие методы, как UpdateData
на моделях представления, и в конечном итоге вы получите непонятный код спагетти UpdateThis
а также UpdateThat
или одну модель мега-представления в стиле mm8, которая используется всеми видами. Вы этого не хотите.