在已打开的对话框MVVM上的打开对话框

时间:2019-03-09 09:22:56

标签: c# mvvm dialog

我观看了一个很棒的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);
}

2 个答案:

答案 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