Подтвердить что ты не робот

Рекомендации по открытию нового окна с шаблоном MVVM WPF

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

Спасибо.

4b9b3361

Ответ 1

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

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

Ответ 2

Я предпочитаю использовать делегат действия, который вставлен через конструктор 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(() => { });
    }
}

Ответ 3

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

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

Основная идея - viewmodel отправляет сообщение на свое представление. Получающий вид выглядит следующим образом:

OnMsgRecived() {

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

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

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

Ответ 4

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

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

Ответ 5

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