如何在MVVM之后为WPF构建通用/可重复使用的模式对话框 [英] How to build a generic/re-usable modal dialog for WPF following MVVM

查看:81
本文介绍了如何在MVVM之后为WPF构建通用/可重复使用的模式对话框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想构建一个通用/可重用的模式对话框,可以在我们的WPF(MVVM)-WCF LOB应用程序中使用.

我有一个Views和相关的ViewModels,我想使用对话框来显示.视图和ViewModel之间的绑定是使用以类型定位的DataTemplates完成的.

以下是我已经能够起草的一些要求:

  • 我更希望它基于窗口,而不是使用像模式对话框一样的装饰器和控件.
  • 应该从内容中获取最小尺寸.
  • 它应位于所有者窗口的中心.
  • 该窗口不得显示最小化"和最大化"按钮.
  • 应该从内容中获取标题.

做到这一点的最佳方法是什么?

解决方案

我正在回答自己的问题,以帮助其他人找到我在一个地方难以找到的所有答案.上面的问题似乎是一个直截了当的问题,实际上提出了多个问题,我希望在下面充分回答.

在这里.

您将用作通用对话框的WPF窗口如下所示:

<Window x:Class="Example.ModalDialogView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ex="clr-namespace:Example"
        Title="{Binding Path=mDialogWindowTitle}" 
        ShowInTaskbar="False" 
        WindowStartupLocation="CenterOwner"
        WindowStyle="SingleBorderWindow"
        SizeToContent="WidthAndHeight"
        ex:WindowCustomizer.CanMaximize="False"
        ex:WindowCustomizer.CanMinimize="False"
        >
    <DockPanel Margin="3">
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" FlowDirection="RightToLeft">
            <Button Content="Cancel" IsCancel="True" Margin="3"/>
            <Button Content="OK" IsDefault="True" Margin="3" Click="Button_Click" />
        </StackPanel>
        <ContentPresenter Name="WindowContent" Content="{Binding}"/>
    </DockPanel>
</Window>

在MVVM之后,显示对话框的正确方法是通过调解器.要使用调解器,通常还需要一些服务定位器.有关介体的详细信息,请在此处.

我确定的解决方案涉及实现IDialogService接口,该接口通过简单的静态ServiceLocator进行解析. 这篇优秀的代码项目文章对此有详细介绍.请注意文章论坛中的消息.该解决方案还解决了通过ViewModel实例发现所有者窗口的问题.

使用此接口,可以调用IDialogService.ShowDialog(ownerViewModel,dialogViewModel).现在,我从所有者ViewModel调用它,这意味着我在ViewModel之间有硬引用.如果您使用汇总事件,则可能会从导体中调用该事件.

在视图上设置最终将显示在对话框中的最小尺寸不会自动设置对话框的最小尺寸.另外,由于对话框中的逻辑树包含ViewModel,因此不能仅绑定到WindowContent元素的属性. 这个问题可以解决我的问题. /p>

我上面提到的答案还包括将窗口置于所有者中心的代码.

最后,禁用最小化和最大化按钮是WPF本身无法做到的.恕我直言,最优雅的解决方案是使用 解决方案

I'm answering my own question to help others find all answers I struggled to find in one place. What above seems like a straight forward problem, actually presents multiple problems that I hope to answer sufficiently below.

Here goes.

Your WPF window that will serve as the generic dialog can look something like this:

<Window x:Class="Example.ModalDialogView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ex="clr-namespace:Example"
        Title="{Binding Path=mDialogWindowTitle}" 
        ShowInTaskbar="False" 
        WindowStartupLocation="CenterOwner"
        WindowStyle="SingleBorderWindow"
        SizeToContent="WidthAndHeight"
        ex:WindowCustomizer.CanMaximize="False"
        ex:WindowCustomizer.CanMinimize="False"
        >
    <DockPanel Margin="3">
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" FlowDirection="RightToLeft">
            <Button Content="Cancel" IsCancel="True" Margin="3"/>
            <Button Content="OK" IsDefault="True" Margin="3" Click="Button_Click" />
        </StackPanel>
        <ContentPresenter Name="WindowContent" Content="{Binding}"/>
    </DockPanel>
</Window>

Following MVVM, the right way to show a dialog is through a mediator. To use a mediator, you typically require some service locator as well. For mediator specific details, look here.

The solution I settled on involved implementing an IDialogService interface that is resolved through a simple static ServiceLocator. This excellent codeproject article has the details on that. Take note of this message in the article forum. This solution also solves the problem of discovering the owner window via the ViewModel instance.

Using this interface, you can call IDialogService.ShowDialog(ownerViewModel, dialogViewModel). For now, I'm calling this from the owner ViewModel, meaning I have hard references between my ViewModels. If you use aggregated events, you will probably call this from a conductor.

Setting the minimum size on the View that will eventually be displayed in the dialog doesn't automatically set the minimum size of the dialog. Also, since the logical tree in the dialog contains the ViewModel, you can't just bind to the WindowContent element's properties. This question has an answer with my solution.

The answer I mention above also includes code that centers the window on the owner.

Finally, disabling the minimize and maximize buttons is something WPF can't natively do. The most elegant solution IMHO is using this.

这篇关于如何在MVVM之后为WPF构建通用/可重复使用的模式对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆