WPF和Prism的常规对话窗口

时间:2017-01-04 12:02:02

标签: c# wpf mvvm prism prism-6

我尝试在shell窗口中为各种视图管理VM状态,为多个编辑对话的VM状态,模态或非模态以及Windows本身的状态之间切换太多痛苦。

现在我希望重做一个shell窗口,并希望只有一个对话窗口,那么我的Windows和Vms的耦合程度要小得多,我可以将shell的VM管理模式借用到对话框中。的管理。

我看到了很多关于直接管理弹出窗口和不那么通用的非模态的指导,但是是否有任何既定的模式或指导只使用一个对话来托管各种VM?更好的是,Prism中是否还有这样的功能?

我想真正坚持DRY原则,并且在视图和虚拟机中的继承增加了我无法承受的复杂性,这应该是一个应该是快速的第一次迭代原型。

2 个答案:

答案 0 :(得分:4)

我不知道任何开箱即用的解决方案,但创建这样一个可重用的对话框实现并不难。实际上,几年前我实现了类似的东西。好吧,这是另一份工作,所以我再也无法访问代码了。此外,我不记得所有的细节,但我可以尝试给你这样一个实现的基本想法。

您可以创建DialogVm,它提供通用对话框功能。

首先,表示层中的对话框需要什么?通常,三个按钮,如......

  • 应用取消关闭(修改对话框)
  • 确定取消(问题对话框)
  • 确定(如果是留言框)

您可以看到,您需要三个命令(ICommand doc)。实际上,我已经创建了DelegateCommand实现(基于this)。 ICommand.CanExecute确定是禁用还是启用绑定按钮。如果命令为null,则应隐藏该按钮。

(如果您使用正确的布局控件,如果未显示按钮,则会正确调整按钮的位置。)

为了提供超过上述四种情况的支持,我向CommandTitle添加了DelegateCommand属性,以便按钮的内容来自那里。

接下来,您需要一个Title属性作为对话框的标题。所以将其添加到DialogVm

如果您希望能够通过执行命令关闭对话框(仅在必要时,如果它是Window的孩子),则可以关注this approach。当然我已经使用了我在那里描述过的版本。但其他人也看起来很有希望。

最后一个开放点是一个属性,它表示不同的对话框内容。如果我没记错的话,我使用了一小组视图模型和相应的DataTemplates(当然还有TemplateSelector,它提供了基于VM类型的正确模板)。当然,您还需要在对话框中使用ContentPresenter控件,该控件显示DataTemplate提供的TemplateSelector

这是唯一的缩减,如果您只有几种不同的对话框类型(例如问题框,消息框......),这只是一种很好的方法。

使用非常简单。简单地说,使用所需的DialogVm逻辑初始化ICommand实例, DialogContentVm (但是您要调用它),将其传递给 DialogWindow (也许,你想使用某种不同的例如弹出窗口)并将其呈现给用户。

嗯,我希望它有所帮助。如果您需要更多信息或任何帮助,请告诉我。

答案 1 :(得分:2)

这实际上非常简单,但有一些复杂性。首先,您需要创建自定义对话框服务。这项服务可以像您一样简单或复杂。这项服务的主要功能是显示一个对话框,该对话框被视为自己的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