WPF 和 Prism 的通用对话框 window
General dialog window for WPF and Prism
我经历了太多的痛苦,试图在 shell window 中的各种视图的 VM 状态管理与大量编辑对话框(模式或非模式)的 VM 状态之间切换,并为 windows 自己声明。
现在我想重做一个shellwindow,希望只有一个对话window,那么我的windows和Vms的耦合度就小多了,而且我可以借用 shell 的 VM 管理模式到对话的管理中。
我看到很多直接管理弹出窗口和不太通用的非模态窗口的指南,但是是否有任何既定的模式或指南可以仅使用一个对话来托管各种 VM?更好的是,Prism 中是否已经提供了此类功能?
我真的想坚持 DRY 原则,视图和 VM 中的继承增加了复杂性,我无法承受本应快速的第一次迭代原型。
嗯,我不知道有什么 开箱即用的 解决方案,但是创建这样一个可重用的对话框实现并不难。实际上,几年前我就实现了类似的东西。好吧,那是在另一份工作中,所以我无法再访问代码了。另外,我不记得所有的细节,但我可以尝试给你这样一个实现的基本思路。
您可以创建一个 DialogVm
,它提供通用对话框功能。
首先,表现层的对话需要什么?通常,三个按钮,例如...
- 应用、取消和关闭(修改对话框)
- 确定和取消或是和否(问题对话框)
- 确定(如果是消息框)
如您所见,您需要三个命令 (ICommand
doc). Actually, I've created a DelegateCommand
implementation (based on this)。 ICommand.CanExecute
确定绑定按钮是禁用还是启用。如果命令为空,则应隐藏该按钮。
(如果您使用的是正确的布局控件,如果未显示按钮,则按钮的位置会适当调整。)
为了支持以上四种场景,我在DelegateCommand
中加了一个CommandTitle
属性,这样按钮的内容就从那里来了
接下来您需要 Title
属性 作为对话框的标题。所以将其添加到 DialogVm
。
如果你想通过执行命令关闭对话框(只需要,如果它是Window
的child),你可以按照this approach。当然,我已经使用了我在那里描述的版本。但其他人也看起来很有前途。
最后打开的点是一个属性,代表不同的对话内容。如果我没记错的话,我使用了一小组视图模型和相应的 DataTemplates
(当然还有 TemplateSelector
,它根据 VM 类型提供正确的模板)。当然,您还需要在对话框中使用 ContentPresenter
控件,它显示 TemplateSelector
.
提供的 DataTemplate
这是唯一的下站,如果您只有几种不同的对话框类型(例如问题框、消息框...),这只是一个好方法
使用非常简单。简单地,用所需的 ICommand
逻辑初始化一个 DialogVm
实例, DialogContentVm (无论你想如何调用它),将它传递给 DialogWindow(也许,您想使用其他东西,例如弹出窗口)并将其呈现给用户。
好吧,希望对您有所帮助。如果您需要更多信息或任何帮助,请告诉我。
这实际上很简单,但有一些复杂性。首先,您需要创建一个自定义对话服务。这项服务可以根据您的喜好简单或复杂。该服务将做的主要事情是显示一个被视为自己的对话框 shell。这意味着对话框将是相同的,但对话框中的内容将根据您在调用它时传递给它的信息而有所不同。所以这意味着一个自定义对话框有它自己的区域。要处理在对话框中使用不同的视图 shell,我会使用导航服务。
您的对话框可能如下所示:
public interface IDialogService
{
void ShowDialog(string uri);
}
public class DialogService : IDialogService
{
private readonly IUnityContainer _container;
private readonly IRegionManager _regionManager;
public DialogService(IUnityContainer container, IRegionManager regionManager)
{
_container = container;
_regionManager = regionManager;
}
public void ShowDialog(string uri)
{
var dialog = _container.Resolve<DialogShell>();
//use a scoped region just in case you can have multiple instances
var scopedRegion = _regionManager.CreateRegionManager();
//set the region manager of the dialog to the scoped region
RegionManager.SetRegionManager(dialog, scopedRegion);
//navigate to show the desired view in the dialog
scopedRegion.RequestNavigate(KnownRegionNames.ContentRegion, uri);
//show the dialog
dialog.Show();
}
}
您可以修改此方法以完全满足您的需要,但您明白了。
编辑:我还想提一下,您甚至可以通过允许您的对话框在其中拥有自己的单独导航并且对显示的每个实例都是唯一的来对此感到疯狂。如果您有兴趣,我有一个 Pluralsight 课程可以展示如何执行此操作。 https://www.pluralsight.com/courses/prism-showing-multiple-shells
我经历了太多的痛苦,试图在 shell window 中的各种视图的 VM 状态管理与大量编辑对话框(模式或非模式)的 VM 状态之间切换,并为 windows 自己声明。
现在我想重做一个shellwindow,希望只有一个对话window,那么我的windows和Vms的耦合度就小多了,而且我可以借用 shell 的 VM 管理模式到对话的管理中。
我看到很多直接管理弹出窗口和不太通用的非模态窗口的指南,但是是否有任何既定的模式或指南可以仅使用一个对话来托管各种 VM?更好的是,Prism 中是否已经提供了此类功能?
我真的想坚持 DRY 原则,视图和 VM 中的继承增加了复杂性,我无法承受本应快速的第一次迭代原型。
嗯,我不知道有什么 开箱即用的 解决方案,但是创建这样一个可重用的对话框实现并不难。实际上,几年前我就实现了类似的东西。好吧,那是在另一份工作中,所以我无法再访问代码了。另外,我不记得所有的细节,但我可以尝试给你这样一个实现的基本思路。
您可以创建一个 DialogVm
,它提供通用对话框功能。
首先,表现层的对话需要什么?通常,三个按钮,例如...
- 应用、取消和关闭(修改对话框)
- 确定和取消或是和否(问题对话框)
- 确定(如果是消息框)
如您所见,您需要三个命令 (ICommand
doc). Actually, I've created a DelegateCommand
implementation (based on this)。 ICommand.CanExecute
确定绑定按钮是禁用还是启用。如果命令为空,则应隐藏该按钮。
(如果您使用的是正确的布局控件,如果未显示按钮,则按钮的位置会适当调整。)
为了支持以上四种场景,我在DelegateCommand
中加了一个CommandTitle
属性,这样按钮的内容就从那里来了
接下来您需要 Title
属性 作为对话框的标题。所以将其添加到 DialogVm
。
如果你想通过执行命令关闭对话框(只需要,如果它是Window
的child),你可以按照this approach。当然,我已经使用了我在那里描述的版本。但其他人也看起来很有前途。
最后打开的点是一个属性,代表不同的对话内容。如果我没记错的话,我使用了一小组视图模型和相应的 DataTemplates
(当然还有 TemplateSelector
,它根据 VM 类型提供正确的模板)。当然,您还需要在对话框中使用 ContentPresenter
控件,它显示 TemplateSelector
.
DataTemplate
这是唯一的下站,如果您只有几种不同的对话框类型(例如问题框、消息框...),这只是一个好方法
使用非常简单。简单地,用所需的 ICommand
逻辑初始化一个 DialogVm
实例, DialogContentVm (无论你想如何调用它),将它传递给 DialogWindow(也许,您想使用其他东西,例如弹出窗口)并将其呈现给用户。
好吧,希望对您有所帮助。如果您需要更多信息或任何帮助,请告诉我。
这实际上很简单,但有一些复杂性。首先,您需要创建一个自定义对话服务。这项服务可以根据您的喜好简单或复杂。该服务将做的主要事情是显示一个被视为自己的对话框 shell。这意味着对话框将是相同的,但对话框中的内容将根据您在调用它时传递给它的信息而有所不同。所以这意味着一个自定义对话框有它自己的区域。要处理在对话框中使用不同的视图 shell,我会使用导航服务。
您的对话框可能如下所示:
public interface IDialogService
{
void ShowDialog(string uri);
}
public class DialogService : IDialogService
{
private readonly IUnityContainer _container;
private readonly IRegionManager _regionManager;
public DialogService(IUnityContainer container, IRegionManager regionManager)
{
_container = container;
_regionManager = regionManager;
}
public void ShowDialog(string uri)
{
var dialog = _container.Resolve<DialogShell>();
//use a scoped region just in case you can have multiple instances
var scopedRegion = _regionManager.CreateRegionManager();
//set the region manager of the dialog to the scoped region
RegionManager.SetRegionManager(dialog, scopedRegion);
//navigate to show the desired view in the dialog
scopedRegion.RequestNavigate(KnownRegionNames.ContentRegion, uri);
//show the dialog
dialog.Show();
}
}
您可以修改此方法以完全满足您的需要,但您明白了。
编辑:我还想提一下,您甚至可以通过允许您的对话框在其中拥有自己的单独导航并且对显示的每个实例都是唯一的来对此感到疯狂。如果您有兴趣,我有一个 Pluralsight 课程可以展示如何执行此操作。 https://www.pluralsight.com/courses/prism-showing-multiple-shells