Я немного опоздал, но я считаю, что существующие ответы недостаточны. Я объясню почему. В общем:
- можно получить доступ к ViewModels из View,
- неправильный доступ к Views из ViewModels , потому что он вводит циклическую зависимость и затрудняет тестирование ViewModels.
Ответ Бенни Джобигана:
App.Container.Resolve<MyChildView>().ShowDialog();
это на самом деле ничего не решает. Вы получаете доступ к своему представлению из ViewModel в тесной связи. Единственное отличие от new MyChildView().ShowDialog()
в том, что вы прошли через слой косвенности. Я не вижу никаких преимуществ перед прямым вызовом ctor MyChildView.
Было бы чище, если бы вы использовали интерфейс для представления:
App.Container.Resolve<IMyChildView>().ShowDialog();`
Теперь ViewModel не сильно связан с представлением. Однако я нахожу весьма непрактичным создание интерфейса для каждого представления.
Ответ арконавта:
Messenger.Default.Send(new DialogMessage(...));
лучше. Похоже, что Messenger, EventAggregator или другие шаблоны pub / sub являются универсальным решением для всего в MVVM :). Недостатком является то, что сложнее отлаживать или переходить к DialogMessageHandler
. Это слишком косвенно, имхо. Например, как бы вы прочитали вывод из диалога? изменив DialogMessage?
Мое решение:
вы можете открыть окно из MainWindowViewModel следующим образом:
var childWindowViewModel = new MyChildWindowViewModel(); //you can set parameters here if necessary
var dialogResult = DialogService.ShowModal(childWindowViewModel);
if (dialogResult == true) {
//you can read user input from childWindowViewModel
}
DialogService использует только ViewModel диалогового окна, поэтому ваши view-модели полностью независимы от Views. Во время выполнения DialogService может найти подходящее представление (например, с использованием соглашения об именах) и показать его, или оно может быть легко смоделировано в модульных тестах.
в моем случае я использую следующие интерфейсы:
interface IDialogService
{
void Show(IDialogViewModel dialog);
void Close(IDialogViewModel dialog);
bool? ShowModal(IDialogViewModel dialog);
MessageBoxResult ShowMessageBox(string message, string caption = null, MessageBoxImage icon = MessageBoxImage.No...);
}
interface IDialogViewModel
{
string Caption {get;}
IEnumerable<DialogButton> Buttons {get;}
}
где DialogButton указывает DialogResult или ICommand или оба.