这是在WPF和MVVM中创建对话框的错误方法吗?

这是在WPF和MVVM中创建对话框的错误方法吗?,mvvm,wpf,Mvvm,Wpf,我有一个使用该模式的WPF应用程序,我需要从我的主体视图模型显示一个对话框 我有一个带有视图模型的二级视图,我想我有两个选项来创建对话框 选项1 在主体视图模型中,我可以执行以下操作: 创建对话框的视图 创建对话框的de视图模型 将视图模型指定给视图 显示对话框 选项2 在主体视图模型中: 创建对话框的视图模型 在对话框视图模型的构造函数中: 创建对话框的视图 将视图模型指定给视图。在这种情况下,分配“this” 显示对话框 我知道在MVVM中,视图模型必须对视图一无所知,但在第二个选项中,实际

我有一个使用该模式的WPF应用程序,我需要从我的主体视图模型显示一个对话框

我有一个带有视图模型的二级视图,我想我有两个选项来创建对话框

选项1

在主体视图模型中,我可以执行以下操作:

  • 创建对话框的视图
  • 创建对话框的de视图模型
  • 将视图模型指定给视图
  • 显示对话框
  • 选项2

    在主体视图模型中:

  • 创建对话框的视图模型
  • 在对话框视图模型的构造函数中:

  • 创建对话框的视图
  • 将视图模型指定给视图。在这种情况下,分配“this”
  • 显示对话框
  • 我知道在MVVM中,视图模型必须对视图一无所知,但在第二个选项中,实际上,视图模型如何没有任何链接到视图的属性,只是在构造函数中创建一个显示,在最终状态下,视图模型对视图一无所知

    但是,我认为主体视图中的代码更清晰,因为我只需要创建视图模型,只需要一行代码,而不是需要4行的选项1(创建视图、创建视图模型、将视图模型指定给视图并显示对话框)


    如果我想遵循这种模式,那么我认为第二个选项不是个坏主意,这是不是错了?

    在大多数情况下,有几种方法可以实现解决方案

    对于具有多个对话框、窗口或页面的大型应用程序,最好的方法是使用服务,例如
    IDialogHandler
    。通过c_-tor提供给虚拟机。你可以从中找到一个例子。
    最大的优点是解耦,这使得vm易于测试,因为它们没有对视图的引用

    对于具有2或3个不同对话框的小型应用程序,以下方法也适用

    public class DialogView : Window
    {
        // a method to create easily a dialog
        public static void ShowDialog(DialogViewModelBase dialogVm)
        {
            var dialog = new DialogView { DataContext = dialogVm };
            dialog.ShowDialog(); // pls note, that this will create a modal dialog
        }
    }
    
    因此可以从任何地方调用
    DialogView.ShowDialog(…)
    。但在这里,虚拟机有一个对视图的引用。
    这类似于您的选项1,好吧,步骤顺序不一样,但已经足够接近了。

    我对wpf中的对话框是这样做的

    var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);
    
    ... do anything with the dialog result...
    

    无论你选择哪种方式,都有一个麻烦。
    坦率地说,它不仅与对话框有关,而且与所有窗口有关。而在MVVM中,这可能会成为一种真正的痛苦。当我们同时使用WinForms和WPF时,至少对我们的团队是这样。

    大多数开发人员都忘记了windows的父子关系。
    关于对话框窗口,这会导致UX有点差:由于显示的对话框,对话框可能位于主窗口下方,而主窗口没有响应。(您可以轻松地重新导入它)。

    因此,在MVVM中,您需要以某种方式设置父级。这里重要的是,视图不一定是一个窗口

    下面是我们的做法。
    我们首选ViewModel优先方法。但我们不在VM中注入视图。我们传递IViewService,它负责视图实例化、父子关系和侦听某些事件。

    想想当用户单击右上角的“交叉”按钮时,您的虚拟机如何阻止视图关闭。

    对话框是否总是最顶端?所以它不能进入主窗口。您可以在一个对话框中打开一个新对话框,该对话框将保持在顶部。不,不总是这样。默认情况下,任务栏中显示对话框和父窗口。您可以单击主窗口的标题,它将显示在前景重叠对话框窗口中。试试看。我想你把Window.Show()和Window.ShowDialog()弄混了。试试看。从wpf窗口显示对话框窗口,而不设置对话框的所有者。这样做:var wnd=new main window();wnd.ShowDialog();我不能进入对话框的“下方”。