Prism MVVM - 在 WPF 中的按钮单击命令上从视图模型显示弹出窗口 window

Prism MVVM - Showing Pop up window from viewmodel on a button click command in WPF

我的视图 (UserControl) 中有一个数据网格,其中有一个按钮,要求是在单击该按钮时显示 window。我通过为 window 创建一个对象并调用它的 show 方法来实现它,是的,这是一种错误的方法,所以,我想要一种实现它的标准方法。

我正在使用 Prism 框架,所以我在 window 视图模型中使用 ViewModelLocationProvider 将 window 视图映射到 Window 视图模型。

var table = new Window();

table.Content = new windowViewModel();

table.Show();

这是我在单击按钮时在主视图模型中实现的代码。

它实际上是在打开一个 window,但是 window 上的视图没有加载。

首先,您希望视图模型是 DataContextContent 实际上是视图)。我在这里再次建议 ViewModelLocator,因为它不可能将参数传递给新的 window。可能您想根据单击按钮所在的行显示不同的内容。

new Window { DataContext = new WindowViewModel( myRow ) }.Show();

其次,这种方法没有任何问题,但要注意一点:将显示 window 的代码放在服务中。您想对您的视图模型进行单元测试,但打开真实 windows.

并不顺利
public interface IWindowService
{
    void ShowWindow( SomeParameter parameter );
}

如果将其注入到视图模型中,您仍然可以对其进行测试(验证是否调用了 ShowWindow)。

第三,删除对 new 的调用并替换为对注入工厂的调用。

var viewModel = _viewModelFactory.Create( "some parameter" );

好很多
var viewModel = new ViewModel( "some parameter", new ADependency( new OtherDependency(), new SomeService() );

单例的困难就更不用说了

使用 Prism 7 中引入的IDialogService

首先,对话框视图或 ViewModel 需要像这样实现 IDialogAware 接口:

   class PopupViewModel : BindableBase, IDialogAware
   {
          public string Title => "Popup";
          public event Action<IDialogResult> RequestClose;

    public bool CanCloseDialog()
    {
        return true;
    }

    public void OnDialogClosed()
    {
    }
    public DelegateCommand OkCommand => new DelegateCommand(() =>
    {
        //you can also pass any parameters you want to back pass to the caller
        RequestClose.Invoke(new DialogResult(ButtonResult.OK)); 
    });

    public void OnDialogOpened(IDialogParameters parameters)
    {
       //here you get the parameters you passed;
    }
  }

然后你需要像这样注册你的视图

  containerRegistry.RegisterDialog<Views.Popup>();

使用你将 IDialogService 注入你的 ViewModel 并将其命名为

       this.dialogService.ShowDialog(nameof(Views.Popup), dialogParmaters, (result)=> 
      {
              if(result.Result == ButtonResult.OK)
              {
              }
      });

如果您希望 window 需要实现 IDialogWindow

,您也可以注册您的自定义 window
         containerRegistry.RegisterDialogWindow<MyDialogWindow>();