Страницы

Поиск по вопросам

воскресенье, 15 марта 2020 г.

Связь между ViewModel в паттерне MVVM

#c_sharp #net #wpf #mvvm


Здравствуйте. Хотелось бы вашего совета. Только начинаю использовать MVVM. Допустим,
есть окно MainWindow, в котором находится статус-бар и некоторая индикацию. В это окно
помещается, к примеру, UserControl, где находится некоторое меню.
По логике вещей, у окна и usercontrol'a свои ViewModel. Вопрос: как тогда обратиться
из одной viewmodel в другую? Например, после выполнения некоторого действия из меню,
мне нужно изменить текст в статус-баре.
Конечно передавать объект одной viewmodel'и в другой нельзя. Нарушение инкапсуляции. 
    


Ответы

Ответ 1



В принципе, ничего страшного нету в том, чтобы одна VM знала о другой. Например, корневая VM обычно имеет ссылки на вложенные VM, и образует таким образом дерево. С другой стороны, для сценария, который вы описываете, сообщение проходит из меню к статус-бару, должно работать не так. Для развязки точки, где генерируется событие, и точки где происходит реакция на него, используются команды. Я бы воспользовался такой архитектурой: Пункт меню привязан к команде (RoutedUICommand). Например, одной из ApplicationCommands, или вы можете определить свою команду тоже¹. Вам нужно будет зарегистрировать обработчики для команд при помощи CommandBinding, глобально через CommandManager.RegisterClassCommandBinding или локально через XAML (). Таким образом, VM, которая зарегистрировала обработчик команды, получит управление при выборе этой команды в меню. Если результат выполнения устанавливает статус, VM, которая выполняет команду, должна знать кому сообщить об изменении статуса. Поскольку статус один на приложение, вы можете сделать его глобально доступным (VM-синглтон или публичное свойство корневой VM), а можете и развязать эту зависимость при помощи ещё одной команды. Заметьте, что есть более прямой путь работы с командами, когда вы просто определяете класс, имплементирующий интерфейс ICommand (CanExecute + Execute + CanExecuteChanged). Это скорее всего не то, что вам надо, потому что такую команду сложнее «отвязать»: вы должны будете как-то передать экземпляр команды в меню. Для случая RoutedUICommand меню знает только какую команду оно хочет выполнить, а подсоединение исполнителя к команде происходит отдельно и независимо. ¹ Например, так: static class ApplicationExtendedCommands { public static ApplicationExtendedCommands Kaboom = new RoutedUICommand() { Text = "Destroy the planet" }; public static ApplicationExtendedCommands About = new RoutedUICommand() { Text = "About application" }; }

Комментариев нет:

Отправить комментарий