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

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

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

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


Править:

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

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

public interface IController
{
    IControllerConnectionBuilder CreateConnectionBuilder();
}

public interface IControllerConnectionBuilder
{
    ControllerConnection BuildConnection();
}

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

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

18
задан lokusking 27 September 2016 в 07:33
поделиться

3 ответа

Вариант, который хорошо работает для взаимодействия между моделями просмотра, - это прямая привязка к классам наблюдателя , находящимся между классами модели просмотра. .

3
ответ дан 30 November 2019 в 09:40
поделиться

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

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

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

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

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

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

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

Звучит ли это жизнеспособным?

3
ответ дан 30 November 2019 в 09:40
поделиться

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

HTH

0
ответ дан 30 November 2019 в 09:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: