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 上的视图没有加载。
首先,您希望视图模型是 DataContext
(Content
实际上是视图)。我在这里再次建议 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>();
我的视图 (UserControl) 中有一个数据网格,其中有一个按钮,要求是在单击该按钮时显示 window。我通过为 window 创建一个对象并调用它的 show 方法来实现它,是的,这是一种错误的方法,所以,我想要一种实现它的标准方法。
我正在使用 Prism 框架,所以我在 window 视图模型中使用 ViewModelLocationProvider 将 window 视图映射到 Window 视图模型。
var table = new Window();
table.Content = new windowViewModel();
table.Show();
这是我在单击按钮时在主视图模型中实现的代码。
它实际上是在打开一个 window,但是 window 上的视图没有加载。
首先,您希望视图模型是 DataContext
(Content
实际上是视图)。我在这里再次建议 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
containerRegistry.RegisterDialogWindow<MyDialogWindow>();