27

I have a WPF Window which has a among other controls hosts a Frame. In that frame I display different pages. Is there way to make a dialog modal to only a page? When I'm showing the dialog it should not be possible to click on any control on the page but it should be possible to click on a control on the same window that is not on the page.

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Robert Höglund
  • 10,010
  • 13
  • 53
  • 70

4 Answers4

27

If I am correct in interpreting your message, you want something that works similar to what Billy Hollis demonstrates in his StaffLynx application.

I recently built a similar control and it turns out that this sort of idea is relatively simple to implement in WPF. I created a custom control called DialogPresenter. In the control template for the custom control, I added markup similar to the following:

<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>

I also added a Show(Control view) method, which finds the the 'PART_DialogView', and adds the passed in view to the Content property.

This then allows me to use the DialogPresenter as follows:

<controls:DialogPresenter x:Name="DialogPresenter">
  <!-- Normal parent view content here -->
  <TextBlock>Hello World</TextBlock>
  <Button>Click Me!</Button>
</controls:DialogPresenter>

To the buttons event handler (or bound command), I simply call the Show() method of the DialogPresenter.

You can also easily add ScaleTransform markup to the DialogPresenter template to get scaling effects shown in the video. This solution has neat and tidy custom control code, and a very simple interface for your UI programming team.

Hope this helps!

Brad Leach
  • 16,857
  • 17
  • 72
  • 88
  • Yes, I got the idea from the StaffLynx application. I find it really hard to grok this WPF stuff but I guess it will get easier. To get the dialog to be moveable I guess there are some more things that must be done. – Robert Höglund Oct 06 '08 at 10:49
  • Certainly - to do the moveable view, you would substitute a Canvas where we have the Grid named "Dialog". You would also have to do all the drag/drop stuff. There is a good overview of this concept at: http://www.codeproject.com/KB/WPF/DraggingElementsInCanvas.aspx – Brad Leach Oct 06 '08 at 10:59
  • Hi Brad, great answer! Would you share the complete source code of the DialogPresenter? I'd love to use it in one of my projects. Thanks, Jens. – FantaMango77 Oct 07 '08 at 07:38
  • I've written up a blog post and released some sample code at: http://bradleach.wordpress.com/2009/02/25/control-level-modal-dialog/ – Brad Leach Feb 25 '09 at 01:36
  • Its not really modal though. Not like MessageBox.Show() is modal and blocks callers until dismissed. It is pseudo-modal because if used properly it takes over the entire window, but it doesn't block like a modal dialog would. – jrwren Sep 09 '11 at 19:39
  • You're spot on, @jrwen. The calling code is not blocked when I call Show(). The design I presented was mainly to show how you could do what Billy Hollis showed in his StaffLynx video - which was essentially multiple non-blocking "modal" dialogs. For this style of UI, you would not want to block. That all said, if you want blocking for a single view, it shouldn't be too hard to implement. – Brad Leach Sep 09 '11 at 21:58
  • I've used a similar approach to this: blocking click interaction on background controls using a border / rectangle. I realized later that the user can still tab into controls that are behind this "visual shield." May not be a big deal, but it's still there. – Josh G Jun 07 '12 at 16:31
4

I have a project on github which is a custom FrameworkElement that allows you to display modal content over the primary content.

The control can be used like this:

<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>

Features:

  • Displays arbitrary content.
  • Does not disable the primary content whilst the modal content is being displayed.
  • Disables mouse and keyboard access to the primary content whilst the modal content is displayed.
  • Is only modal to the content it is covering, not the entire application.
  • can be used in an MVVM friendly way by binding to the IsModal property.
Benjamin Gale
  • 12,977
  • 6
  • 62
  • 100
2

Why not just use nested message pumps to create modal controls

http://deanchalk.com/wpf-modal-controls-via-dispatcherframe-nested-message-pumps/

Pang
  • 9,564
  • 146
  • 81
  • 122
Dean Chalk
  • 20,076
  • 6
  • 59
  • 90
1

You are not looking for a modal dialog here. You need a function that will disable the "page" control, show a dialog, and re-enable it when the dialog closes.

I'm not too sure whether you understand what a modal dialog is meant to do though?

Mez
  • 24,430
  • 14
  • 71
  • 93
  • Why the downvote? A Modal window is a window that is the only window that can accept input at that time for an application. – Mez Jan 13 '11 at 15:26