Лучшие практики для открытия нового окна с шаблоном WPF MVVM - PullRequest
20 голосов
/ 24 ноября 2010

Я уже некоторое время размышляю об этом ... Как лучше всего открыть новое окно (view & viewmodel) из другой модели представления, ЕСЛИ мы помним, что модель представления, которая открывает новое окно, не знаетсуществование этого представления (как и должно быть).

Спасибо.

Ответы [ 5 ]

13 голосов
/ 24 ноября 2010

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

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        DataContext = new MainViewModel(() => (new Window()).Show()); // would be actual window
    }
}

public class MainViewModel
{
    private Action popupAction;
    public MainViewModel(Action popupAction)
    {
        this.popupAction = popupAction;
    }

    public ICommand PopupCommand { get; set; }

    public void PopupCommandAction()
    {
        popupAction();
    }
}

public class SomeUnitTest
{
    public void TestVM()
    {
        var vm = new MainViewModel(() => { });
    }
}
5 голосов
/ 02 декабря 2010

Я не использую ViewModel, чтобы открыть другой View / ViewModel.За это отвечает контролер.ViewModel может сообщить контроллеру (например, через событие), что пользователь ожидает увидеть следующий вид.Контроллер создает View / ViewModel с помощью контейнера IoC.

Как это работает, показано в примере приложения ViewModel (EmailClient) WPF Application Framework (WAF) .

3 голосов
/ 24 ноября 2010

Используйте шаблон-посредник, такой как класс сообщений mvvmlight:

http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338

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

OnMsgRecived() {

  Viewmodel vm = New Viewmodel() - Or use dependency injection to resolve

  View v = new View()
  v.DataContext = vm
  v.Show()
}

Это позволяет модели представления, отправившей сообщение, показать другое окно без «знания» о том, как или кто сделал открытие.

2 голосов
/ 02 декабря 2010

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

Шаблон-посредник только делает это более свободно связанным и позволяетдля возможностей, где основное окно приложения View или вложенный View может прослушивать сообщения глобально в приложении, не имея прямого доступа к ViewModels, чтобы прикрепить обработчики событий и тому подобное.Чтобы отфильтровать сообщения, которые не имеют отношения к делу, вы можете посмотреть на какое-либо значение источника сообщения или другое указание на то, откуда исходит сообщение.Для тех, кому нравится идея Windows Messages и как это работает между различными элементами управления (Windows) в рамках неуправляемой разработки и разработки WinForms, может быть способ понять, что система может быть построена поверх посредника, который передает сообщения.

0 голосов
/ 25 ноября 2010

Я согласен с подходом, подобным посреднику, но OnMsgReceived четко обрабатывается в коде кода представления, есть ли хороший способ избежать этого?

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