Открыть диалог в WPF MVVM - PullRequest
       16

Открыть диалог в WPF MVVM

10 голосов
/ 27 ноября 2009

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

На данный момент я делаю это так (работает нормально)

  • Нажатие кнопки генерирует команду в ViewModel.
  • ViewModel вызывает событие, которое слушает контроллер.
  • Контроллер обрабатывает детали нового окна (т.е. View, ViewModel & model) и открывает его (ShowDialog)
  • Когда окно закрыто, Контроллер добавляет результат к событиям и возвращает к ViewModel
  • ViewModel передает информацию в модель.

Есть много шагов, но все они имеют смысл, и не так много печатать.

Код выглядит следующим образом (в окне запрашивается имя пользователя)

ViewModel:

AskUserNameCommand = DelegateCommand(AskUserNameExecute);
...

public event EventHandler<AskUserEventArgs> AskUserName;

void AskUserNameExecute(object arg) {
    var e = new AskUserNameEventArgs();
    AskUserName(this, e);
    mModel.SetUserName(e.UserName);
}

Контроллер:

mViewModel.AskUserName += (sender,e) => {
    var view = container.Resolve<IAskUserNameView>();
    var model = container.Resolve<IAskUserNameModel>();
    var viewmodel = container.Resolve<IAskUserNameViewModel>(view, model);
    if (dlg.ShowDialog() ?? false)
        e.UserName = model.UserName;
}

У меня вопрос, как работает горизонтальная связь в шаблоне MVVM. Каким-то образом кажется неправильным позволять контроллеру участвовать в передаче данных между моделями.

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

Ответы [ 5 ]

12 голосов
/ 29 ноября 2009

Мне не нравятся большинство текущих предложений по той или иной причине, поэтому я подумал, что я бы связал почти идентичный вопрос с ответами, которые я делаю , например:

Диалог открытия файла MVVM

Конкретно ответ Камерона Макфарланда - именно то, что я делаю. Служба, предоставляемая через интерфейс для обеспечения ввода-вывода и / или взаимодействия с пользователем - это путь, по следующим причинам :

  • Тестируется
  • Он абстрагирует реализацию любых диалогов , так что ваша стратегия обработки этих типов вещей может быть изменена без влияния на составной код
  • Не полагается ни на какие шаблоны связи . Многие предложения, которые вы видите, основаны на посреднике, таком как агрегатор событий. Эти решения основаны на двустороннем взаимодействии с партнерами по другую сторону от посредника, что является сложным для реализации и очень свободным контрактом.
  • ViewModels остаются автономными . Я, как и вы, не чувствую себя хорошо, учитывая связь между контроллером и ViewModel. ViewModel должен оставаться автономным, если по какой-либо другой причине это не облегчает тестирование.

Надеюсь, это поможет.

2 голосов
/ 14 февраля 2011

я использую этот подход для диалогов с mvvm.

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

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);
0 голосов
/ 27 ноября 2009

Я использовал EventAggregator из Prism v2 в подобных сценариях. Хорошая вещь о prims заключается в том, что вам не нужно использовать весь фреймворк в приложении MVVM. Вы можете извлечь функциональность EventAggregator и использовать ее вместе с текущими настройками.

0 голосов
/ 29 ноября 2009

Вы можете взглянуть на эту статью MVVM. Он описывает, как контроллер может взаимодействовать с ViewModel:

http://waf.codeplex.com/wikipage?title=Model-View-ViewModel%20Pattern&ProjectName=waf

0 голосов
/ 27 ноября 2009

Я сталкивался с подобными проблемами. Вот как я их решил и почему я сделал то, что сделал.

Мое решение:

Мой MainWindowViewModel имеет свойство типа ModalViewModelBase, называемое Modal. Если мой код нуждается в определенном представлении, чтобы быть модальным, он помещает ссылку на него в это свойство. MainWindowView отслеживает это свойство с помощью механизма INotifyPropertyChanged. Если для Modal установлено значение некоторой виртуальной машины, класс MainWindowView возьмет виртуальную машину и поместит ее в окно ModalView, где соответствующий элемент UserControl будет отображаться с помощью магии DataTemplates, окно отображается с использованием ShowDialog. ModalViewModelBase имеет свойство для DialogResult и свойство с именем IsFinished. Когда для модальной виртуальной машины IsFinished установлено значение true, представление закрывается.

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

Мои рассуждения:

Принцип модальных представлений заключается в том, что другие виды отключены, а модальные отображаются. Это часть логики взгляда, которая по сути не выглядит. Вот почему у меня есть свойство для этого в MainWindowViewModel. Если бы я пошел дальше, я должен сделать все остальные свойства или команды для всех других ВМ в исключениях выброса Основной ВМ, находясь в модальном режиме, но я чувствую, что это излишне.

Механизм View, фактически запрещающий пользователю любые другие действия, не должен выполняться с помощью всплывающего окна и showdialog, возможно, вы поместили модальное представление в существующее окно, но отключили все остальные или некоторые другие вещь. Эта логика, связанная с представлением, относится к самому представлению. (То, что типичный разработчик не может кодировать эту логику, кажется второстепенным. Нам всем иногда нужна помощь.)

Так вот, как я это сделал. Я предлагаю это только как предложение, возможно, есть и другие способы думать об этом, и я надеюсь, что вы также получите больше ответов.

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