如何在我的WPF应用程序中为页面创建模态对话框?

27

我有一个WPF窗口,其中包含一个框架和其他控件。在该框架中,我显示不同的页面。有没有一种方法可以使对话框对某个页面具有模态性?当我显示对话框时,应该无法单击页面上的任何控件,但应该可以单击不在页面上的同一窗口上的控件。

4个回答

27
如果我正确理解了您的信息,您想要类似于Billy Hollis在他的StaffLynx应用程序中展示的内容的东西。
最近我建立了一个类似的控件,事实证明这种想法在WPF中相对简单。我创建了一个名为DialogPresenter的自定义控件。在自定义控件的控件模板中,我添加了类似以下标记的标记:
<ControlTemplate TargetType="{x:Type local=DialogPresenter}">
  <Grid>
    <ContentControl>
      <ContentPresenter />
    </ContentControl>
    <!-- The Rectangle is what simulates the modality -->
    <Rectangle x:Name="Overlay" Visibility="Collapsed" Opacity="0.4" Fill="LightGrey" />
    <Grid x:Name="Dialog" Visibility="Collapsed">
      <!-- The template for the dialog goes here (borders and such...) -->
      <ContentPresenter x:Name="PART_DialogView" />
    </Grid>
  </Grid>
  <ControlTemplate.Triggers>
    <!-- Triggers to change the visibility of the PART_DialogView and Overlay -->
  </ControlTemplate.Triggers>
</ControlTemplate>

我还添加了一个Show(Control view)方法,该方法查找'PART_DialogView',并将传入的视图添加到Content属性中。这样我就可以按照以下方式使用DialogPresenter:
<controls:DialogPresenter x:Name="DialogPresenter">
  <!-- Normal parent view content here -->
  <TextBlock>Hello World</TextBlock>
  <Button>Click Me!</Button>
</controls:DialogPresenter>

对于按钮事件处理程序(或绑定的命令),我只需调用DialogPresenter的Show()方法即可。
您还可以轻松地向DialogPresenter模板添加ScaleTransform标记以获得视频中显示的缩放效果。这个解决方案具有整洁的自定义控件代码和非常简单的界面,适用于您的UI编程团队。
希望这可以帮助您!

是的,我从StaffLynx应用程序中得到了灵感。我发现理解这个WPF的东西真的很难,但我想它会变得更容易。为了使对话框可移动,我想还需要做一些其他的事情。 - Robert Höglund
当然 - 要做可移动视图,您需要在我们名为“Dialog”的网格的位置替换画布。您还必须完成所有拖放的操作。这个概念有一个很好的概述:http://www.codeproject.com/KB/WPF/DraggingElementsInCanvas.aspx。 - Brad Leach
嗨Brad,非常好的答案!你能分享一下DialogPresenter的完整源代码吗?我很想在我的一个项目中使用它。 谢谢,Jens。 - FantaMango77
你说得对,@jrwen。当我调用Show()时,调用代码并没有被阻塞。我提出的设计主要是为了展示如何实现Billy Hollis在他的StaffLynx视频中展示的多个非阻塞“模态”对话框。对于这种类型的用户界面,您不希望被阻塞。尽管如此,如果您想要单个视图的阻塞,实现起来也不应该太难。 - Brad Leach
我曾经使用过类似的方法:使用边框/矩形来阻止背景控件的点击交互。后来我意识到用户仍然可以通过“视觉屏障”进入位于其后面的控件。这可能不是一个大问题,但它确实存在。 - Josh G
显示剩余2条评论

4

我在 Github 上有一个项目,它是一个自定义的 FrameworkElement ,可以让你在主要内容上方显示模态内容。

这个控件可以像这样使用:

<c:ModalContentPresenter IsModal="{Binding DialogIsVisible}">
    <TabControl Margin="5">
            <Button Margin="55"
                    Padding="10"
                    Command="{Binding ShowModalContentCommand}">
                This is the primary Content
            </Button>
        </TabItem>
    </TabControl>

    <c:ModalContentPresenter.ModalContent>
        <Button Margin="75"
                Padding="50"
                Command="{Binding HideModalContentCommand}">
            This is the modal content
        </Button>
    </c:ModalContentPresenter.ModalContent>

</c:ModalContentPresenter>

特点:

  • 显示任意内容。
  • 在模态内容显示时不会禁用主要内容。
  • 在模态内容显示时禁用对主要内容的鼠标和键盘访问。
  • 仅对其覆盖的内容进行模态,而不是整个应用程序。
  • 可以通过绑定到IsModal属性以MVVM友好的方式使用。

2

2
链接已失效。 - StayOnTarget

1

你不需要一个模态对话框。你需要一个能够禁用“页面”控件、显示对话框并在对话框关闭时重新启用它的函数。

我不确定你是否理解模态对话框的作用?


为什么要踩?模态窗口是应用程序中在此时唯一能够接受输入的窗口。 - Mez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接