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

MVVM: Как обрабатывать взаимодействие между вложенными ViewModels?

Я экспериментирую с часто упоминаемым шаблоном MVVM, и в некоторых случаях мне сложно определить четкие границы. В моем приложении у меня есть диалог, который позволяет мне создать соединение с контроллером. Для диалога есть класс ViewModel, который достаточно прост. Однако в диалоговом окне также содержится дополнительный элемент управления (выбранный ContentTemplateSelector), который изменяется в зависимости от конкретного типа контроллера, который подключен. Этот элемент управления имеет свой собственный ViewModel.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я закрываю диалоговое окно, нажимая "ОК", мне нужно создать запрошенное соединение, для которого требуется информация, записанная во внутреннем классе ViewModel, соответствующем контроллеру. Заманчиво просто, чтобы все классы ViewModel, специфичные для контроллера, реализовали общий интерфейс, который конструирует соединение, но должен ли внутренний ViewModel отвечать за эту конструкцию?

Мой общий вопрос: существуют ли общепринятые шаблоны проектирования для того, как ViewModels должны взаимодействовать с eachother, особенно когда "родительская" VM нуждается в помощи от "дочерней" виртуальной машины, чтобы знать, что делать?


EDIT:

Я придумал дизайн, который немного чище, чем я изначально думал, но я все еще не уверен, что это "правильный" способ сделать это. У меня есть некоторые вспомогательные службы, которые позволяют ContentTemplateSelector просматривать экземпляр Controller и псевдомагически находить элемент управления, отображаемый для построителя соединений. Что меня беспокоило, так это то, что мой ViewModel на верхнем уровне должен будет смотреть на DataContext для сгенерированного элемента управления и передавать его соответствующему интерфейсу, который кажется плохим (почему в представлении DataContext есть что-либо создать соединение?)

Я получил что-то вроде этого (упрощая):

public interface IController
{
    IControllerConnectionBuilder CreateConnectionBuilder();
}

public interface IControllerConnectionBuilder
{
    ControllerConnection BuildConnection();
}

У меня есть мой внутренний класс класса ViewModel IControllerConnectionBuilder, и контроллер возвращает внутреннюю ViewModel. Затем ViewModel верхнего уровня визуализирует этот IControllerConnectionBuilder (через псевдомагический механизм). Мне по-прежнему немного беспокоит, что это мой внутренний ViewModel, выполняющий здание, но по крайней мере теперь мой топ-уровень ViewModel не должен знать о грязных деталях (он даже не знает и не заботится о том, чтобы визуализированный элемент управления использовал ViewModel).

Я приветствую дополнительные мысли, если есть способы убрать это дальше. Мне все еще не ясно, сколько ответственности за просмотр ViewModel.

4b9b3361

Ответ 1

Опция, которая хорошо работает для взаимодействия между режимами просмотра, заключается в непосредственном привязке к классам observer, сидящим между классами viewmodel.

Ответ 2

Я думаю, вы хотите, чтобы ваш топ-уровень ViewModel знал о существовании NestedViewModel, он имеет смысл с иерархической точки зрения, главный вид содержит дочерний вид.

На мой взгляд, ваш инстинкт прав, но вложенный ViewModel не кажется правильным, чтобы выставлять поведение, инициированное действиями пользователя на верхнем уровне. Вместо этого верхний уровень ViewModel должен обеспечивать поведение для представления, с которым он связан.

Но я бы подумал о переносе ответственности за построение соединения в ICommand и разоблачении этой команды с помощью верхнего уровня ViewModel. Затем кнопку OK в главном диалоговом окне вы связываете с этой командой, и команда просто делегирует верхний уровень ViewModel, например, вызывает ViewModel.CreateConnection(), когда он выполняется.

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

Единственная морщина будет, если разные типы NestedViewModel выставляют радикально различный набор данных.

Например, один из них предоставляет свойства HostName и Порт как свойства, а другой предоставляет Имя пользователя и Пароль.

В этом случае вам может потребоваться выполнить некоторую инфраструктурную работу, чтобы ваш топ-уровень ViewModel.CreateConnection() работал по-чистым. Хотя, если у вас есть небольшое количество вложенных типов управления, это может не стоить усилий, и простой NestedViewModel тип-проверка и литье могут быть достаточными.

Является ли это жизнеспособным?

Ответ 3

Недавно я экспериментировал с Unity (Microsoft Enterprise library) для использования инъекции зависимостей. Это может быть маршрут для использования при использовании интерфейсов, которые полностью определяют, что обе модели просмотра не должны друг от друга. MEF будет другим вариантом для инъекций зависимостей, о которых я знаю.

НТН