我观看了一个很棒的video关于创建DialogService的信息,该服务将在MVVM中打开对话框。由于DialogService构造函数将所有者(窗口类型)作为参数,因此在MainWindow中创建dialogService很容易。只需在App.xaml.cs中分别为MainWindow创建一个View和一个ViewModel并连接所有东西。但是问题是,如何在从MainWindow打开的对话框中创建dialogService(以从该对话框打开更多对话框),因为无法获取从MainWindowViewModel打开的对话框的View实例。这是显示该对话框的方法。
private void ShowAdministrationDialog()
{
AdministrationDialogViewModel viewModel = new AdministrationDialogViewModel(this.context);
dialogService.ShowDialog(viewModel);
}
答案 0 :(得分:1)
视频中的代码不支持您的用例。对话框服务似乎是单例,仅能打开主窗口为所有者的对话框。在许多情况下可能还不错,对于其他情况,就像您的情况一样,它根本不起作用。
我创建了一个名为MvvmDialogs的NuGet包,该包能够在所有可能的情况下打开对话框。您可以在GitHub上浏览代码。我已经通过引入一个附加属性解决了这个问题,该属性充当视图和视图模型之间的桥梁。因此,我始终能够从视图模型跳到其视图,并从该视图遍历逻辑UI树,直到到达拥有的窗口。
这只是解决问题的一种方法,如果您希望构建自己的对话框服务,我相信可以找到另一种方法。如果不这样做,总会有MvvmDialogs:D
答案 1 :(得分:0)
有办法解决这个问题,但是我不确定它是否会破坏MVVM,因此FantasticFiasco的解决方案可能更好。在DialogService类中,将ShowDialog的单独方法分为2种方法-PrepareDialog和ShowDialog
PrepareDialog:
public void PrepareDialog<TViewModel>(TViewModel viewModel) where TViewModel : IDialogRequestClose
{
// Finds a ViewType from Mappings
Type viewType = Mappings[typeof(TViewModel)];
// Creates a View instance
IDialog dialog = (IDialog)Activator.CreateInstance(viewType);
// Adds an event on dialog close request
EventHandler<DialogCloseRequestedEventArgs> handler = null;
handler = (sender, e) =>
{
// Dispatch handler
viewModel.CloseRequested -= handler;
// Reset owner's opacity
dialog.Owner.Opacity = 1;
// Returns a result if exists
if (e.DialogResult.HasValue)
{
dialog.DialogResult = e.DialogResult;
}
else
{
dialog.Close();
}
};
dialog.DataContext = viewModel;
dialog.Owner = owner;
dialog.Owner.Opacity = 0.5;
// Adds handler for close request
viewModel.CloseRequested += handler;
// Initializes a dialog service in opening dialog's ViewModel if supports it
IViewModelDialogService viewModelDialogService = viewModel as IViewModelDialogService;
if (viewModelDialogService != null)
{
viewModelDialogService.DialogService = new DialogService((Window)dialog);
}
this.newWindow = (Window)dialog;
}
ShowDialog:
public bool? ShowDialog()
{
if (this.newWindow == null)
{
throw new ArgumentNullException();
}
bool? result = this.newWindow.ShowDialog();
this.newWindow = null;
return result;
}
当然,您需要在对话框服务类中添加私有字段newWindow(类型Window)。现在,这使您可以在调用PrepareDialog时在dialogService中获取视图实例,并在调用PrepareDialog之后可以将更改应用于ViewModel的对话框服务,然后最后调用ShowDialog