Подскажите как показать форму модально с учетом MVVM? Т.е. обычный ShowDialog не подходит явно, т.к. не вписывается в паттерн.
-
Если вам дан исчерпывающий ответ, отметьте его как верный (галочка напротив выбранного ответа). – andreycha Sep 07 '16 at 15:41
1 Answers
Например так:
Для диалогового окна у вас также должна быть вью-модель. В месте, где вы хотите показать диалог, создаете экземпляр этой вью-модели.
Дальше может быть два варианта:
а. Используя специальный сервис. У вас есть некоторый
IDialogService, в котором вы можете зарегистрировать соответствие "вью / вью-модель" на этапе инициализации приложения, а также вызвать показ диалога, передав нужную вью-модель. МетодShowDialog()при этом возвращает значения, аналогичные методуWindow.ShowDialog(). Конкретный экземплярIDialogServiceпередается нужным вью-моделям извне (если вы используете DI) или просто создается по месту необходимости (что хуже).public interface IDialogService { void RegisterDialog<TView, TViewModel>(); bool? ShowDialog<TViewModel>(TViewModel viewModel); }Пример реализации можно посмотреть в ответе VladD.
б. Используя сообщения. У вас есть некоторое сообщение 'ShowDialogMessage', которое вы передаете мессенджеру. На это сообщение подписывается либо какое-то одно окно ("главное"), либо конкретные "родительские" окна. Зависит от желаемой степени детализации. Если при этом нужно получать "возвращаемое значение", то в сообщение нужно просто добавить соответствующее поле, которое будет заполняться в том месте, где сообщение обрабатывается.
public class ShowDialogMessage<TViewModel>: MessageBase { public TViewModel ViewModel { get; private set; } public SomeType Result { get; set; } public ShowDialogMessage(TViewModel viewModel) { ViewModel = viewModel; } }Касаемо мест, где создаются и показываются конкретные диалоговые окна. Их реализация может отличаться в зависимости от того, что вам нужно. Если диалоговое окно (и, соответственно, его вью-модель) у вас дженериковое (например, это просто мессадж бокс, с заголовком, текстом и типом), то это может быть одно место на все приложение. Если же диалоговые окна уникальные, то мест их показа будет несколько -- по месту на "тип" окна. Иногда это можно свести к одному месту, если использовать мапу "диалог / вью-модель" (см. метод
RegisterDialog()в первом способе).
- 25,167
- 4
- 46
- 82
-
а. Как то не очень понятно. Что за интерфейс? Где класс который его реализует? Где он должен создаваться?
б. Тут вроде выглядит как то попроще, но основной вопрос тут в том что событие оно кинется, а код пойдет дальше. Т.е. когда показываются модальные окна код в месте вызова ShowDialog останавливается и ждет закрытия окна, а в этом случае (если я правильно понял) просто кинется событие и код дальше пойдет не дожидаясь закрытия формы.
– Developer May 14 '16 at 18:40 -
@DarkByte он написал типичные подходы. ну а классы надо реализовывать под личные нужды. в случае отправки оповещения код не пойдет дальше пока не будут оповещены и не отработают хендлеры у подписчиков, а если у подписчика есть ShowDialog, то там и остановится, пока диалог не закроется. – vitidev May 14 '16 at 19:34
-
Ну правда вот первый пример совсем не понятен! Пожалуйста можно пример с реализацией? А по второму примеру да, действительно работает так как задумано, только как быть если в разных местах надо показывать разные диалоговые окна? Как их фильтровать? Т.е. в качестве мессенджера я взял mvvm light, там есть готовый. Но там я допустим шлю сообщение просто 0 и по типу int его ловлю в MainWindow и вывожу диалог. А как быть если много диалоговых окон? Не использовать же по типу на каждое... Как то это попахивает говнокодом. – Developer May 15 '16 at 04:00
-
И кстати во втором примере как быть с возвратом значений? Ну например если я показывал не просто диалоговое окно, а MessageBox с кнопками и мне надо значить какую кнопку нажали. – Developer May 15 '16 at 06:17
-
@andreycha И еще такой вопрос: а где вообще эти диалоговые окна должны создаваться? Я сейчас перечитал 3-ый пункт, но не понял :(. Интересует именно вариант когда окна уникальные. Причем мне надо чтобы окно создавалось только один раз! А потом просто показывалось. – Developer May 16 '16 at 09:59
-
Вот смотрите что я набросал: http://pastebin.ru/T7cfWg6U. Но почему то это не работает. Не создается нигде инстанс окна. Разве он из ресурсов не должен создаться? – Developer May 16 '16 at 10:34
-
-
@andreycha, А где должны создаваться дочерние View при использовании мессенджера? В App.xaml.cs? – trydex Jun 26 '17 at 20:41
-
1@maxwell там, где вы обрабатываете сообщение. Потому что с большей долей вероятности это вью будет являться "внутренним" для места обработки сообщения. Возможно также еще гибридные варианты -- когда есть и диалог сервис, и сообщения (оба подпункта 2). – andreycha Jun 27 '17 at 07:46