Правильный способ отображения всплывающих окон с использованием шаблона WPF M-V-VM - PullRequest
9 голосов
/ 02 апреля 2009

У меня был вопрос об ответственности виртуальной машины, когда дело доходит до всплывающих окон. Когда приложение выдает окно сообщения или какой-то диалог (с MVVM), у нас есть два варианта:

  1. помещение кода пользовательского интерфейса (ShowDialog ()) в виртуальную машину, что кажется плохим
  2. пусть ВМ отправляет какое-то событие, на которое пользовательский интерфейс может подписаться, и отображает диалоговое окно в коде (но мы стремимся к нулю кода позади)

Как вы, ребята, справляетесь с этим делом?

Ответы [ 8 ]

2 голосов
/ 14 апреля 2009

Выезд Оникс . Это библиотека M-V-VM (полное раскрытие: я автор), основанная на использовании сервисов и шаблонов поиска сервисов или внедрения зависимостей. Есть сервисы для MessageBox и общие диалоги, и довольно легко добавить свои собственные сервисы.

2 голосов
/ 02 апреля 2009

Не помещайте код пользовательского интерфейса в виртуальную машину, это просто вызывает много головных болей в будущем.

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

Прежде всего, используйте свою голову и доверяйте своим суждениям, вы узнаете, что использовать достаточно скоро.

1 голос
/ 02 апреля 2009

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

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

1 голос
/ 02 апреля 2009

Несколько других опций, не упомянутых другими:

Команда реле

ВМ выполняет команду, которую я люблю называть «релейной командой». Это команда, обработанная кем-то другим, и виртуальной машине все равно, кто. Выполнение команды ничего не делает, кроме как вызывает событие Executed. Ваше представление подпишется на это событие и отобразит содержимое в новом Window (содержимое будет передано в качестве параметра команды).

Обратите внимание, что команда relay не является перенаправленной командой. Он не ищет обработчик в своей логике исполнения. Это просто вызывает событие.

Сервис

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

0 голосов
/ 08 апреля 2009

Иметь ViewModel для всплывающих окон и View как пользовательский элемент управления. В зависимости от сложности всплывающего окна это может быть универсальная виртуальная машина или конкретная виртуальная машина для бизнес-кейса. При попытке отобразить его из родительской виртуальной машины создайте класс «хост» для виртуальной машины всплывающих окон (унаследованный от Window или Popup), покажите его и назначьте ему виртуальную машину. Хост должен нести ответственность за поиск правильного представления (например, через DataTemplate)

В этом случае виртуальная машина вашего всплывающего окна все еще тестируется, и минимальный уровень связи с WPF для родительской виртуальной машины приемлем, IMO.

0 голосов
/ 08 апреля 2009

Я согласен с Карлосом, что использование подписки на события в представлении не является хорошим выбором. Насколько я понимаю MVVM, это приводит к исключению любого кода позади, и мне действительно это нравится :). Одним из преимуществ MVVM является возможность его модульного тестирования. Но я все еще верю, что модель представления может быть протестирована, даже если она открывает окна. Все, что нам нужно, это просто использовать Window с инициализированным контентом с необходимой моделью представления. Я думаю, что может быть 2 возможных ситуации, когда виртуальная машина должна открыть новый диалог: либо показать окно опций / настроек, либо показать окно, которое зависит от бизнес-логики. В первом случае новый код окна является единственным кодом команды (команда для кнопки «Настройки» или «Параметры» / пункт меню). Во втором случае у нас есть некоторая логика принятия решения, которая открывает окно. Но в любом случае мы можем переместить код, который открывает новое окно, в отдельный метод / класс, а при тестировании нашей ВМ просто высмеивать этот метод / класс. Более того, этот отдельный класс может быть своего рода универсальным WindowsController, который будет отслеживать все окна в приложении. Но все же мы можем сказать, что модель представления открывается всплывающим окном с помощью вспомогательного WindowsController, и представление больше ничего не знает о других окнах. Вся бизнес-логика остается включенной в модель и модель представления.

0 голосов
/ 02 апреля 2009

Создайте интерфейс для вашего всплывающего диалога, даже если вы планируете использовать окно сообщения.

В нижней части иерархии представления есть метод, позволяющий докладчику зарегистрировать класс или форму, реализующую всплывающее окно.

Ваши взгляды вызывают зарегистрированное всплывающее окно.

0 голосов
/ 02 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...