Running on Empty

The few things I know, I like to share.

WPF UserControls as a Modal-like Dialog.

Introduction

This article is in direct response to feedback from the WPF Popup Controls series.  What if you needed a User Control to “popup” as a Windows Dialog, have all the properties of a Windows Dialog, but behave as a Popup Control.

Creating a UserControl…plus a little something extra.

Create a WPF User Control as you would normally, but you will want to make certain you put at least one button on the UserControl.

<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="120" Height="50"/>

Now include a RoutedEvent using the Bubble RoutingStrategy for the button you just created.  This will allow any Page or Window that implements this control to intercept the ClickEvent.Place a couple of Methods that will Show and Hide the user control.  You could also create Dependency Properties at this point to pass Properties between the Parent and the UserControl, not shown here though.

namespace TestCase.UserControls
{
    public partial class TestControl : UserControl
    {
        #region Events

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new RoutedEventArgs(CancelButtonClickEvent));
        }

        #endregion

        #region RoutedEvents

        public static readonly RoutedEvent CancelButtonClickEvent = EventManager.RegisterRoutedEvent(
            "CancelButtonClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TestControl));
        public event RoutedEventHandler CancelButtonClick
        {
            add { AddHandler(CancelButtonClickEvent, value); }
            remove { RemoveHandler(CancelButtonClickEvent, value); }
        }
      
        #endregion

        public TestControl()
        {
            InitializeComponent();
        }

        public void Show()
        {
            Visibility = Visibility.Visible;
        }

        public void Hide()
        {
            Visibility = Visibility.Collapsed;
        }
    }
}

Using the UserControl.

You will now need to declare the user control on a Window or Page.  This means the Page or Window Header needs to declare the namespace for your UserControl.

xmlns:UserControls="clr-namespace:TestCase.UserControls"

Now finally we are ready to declare our user control.

<UserControls:TestControl HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch"
                          Width="Auto" Height="Auto" Visibility="Collapsed"
                          x:Name="TestUserControl"
                          CancelButtonClick="TestUserControl_CancelButtonClick" />

Notice the control Visiblilty property is set to Collapsed.  We now need to write the code behind, our main focus will be to display and hide the user control.

private void TestUserControl_CancelButtonClick(object sender, RoutedEventArgs e)
{
    HideTestUserControl();
}

private void ShowTestUserControl()
{
    TestUserControl.Show();
}

private void HideTestUserControl()
{
    TestUserControl.Hide();
}

On the main parent Page or Window, simply wire up a Button click or some other user Event and call ShowTestUserControl().

Making it look Pretty.

You will most likely want to make the background control grey out to indicate focus is now on your User Control as well as steal focus from the Parent Window while the user control is active.  This can easily be accomplished using a rectangle.

Add the following code to your AppStyles.xaml

  <Style x:Key="UserControlOverlayRectangleStyle" TargetType="{x:Type Rectangle}">
    <Setter Property="Fill" Value="#FF151515"/>
    <Setter Property="Opacity" Value="0.61"/>
  </Style>

Also add the following code to your UserControl.

<Grid Opacity="1" Width="Auto" Height="Auto" Background="{x:Null}">
     <Rectangle Name="MainRectangle" Margin="0,0,0,0" Style="{DynamicResource UserControlOverlayRectangleStyle}"/>
     <!-- Everything Else -->
</Grid>

Conclusion

We now have a simple way to add declare user controls on a Page or Window and have them behave as Dialog Windows. 

Please feel free to leave suggestions or comments.  I look forward to your feedback.

January 10, 2008 - Posted by | C#, WPF, XAML

12 Comments »

  1. Thanks… I will try to put into my control… and share further information with you… Thanks again – Shrenik

    Comment by Shrenik Jhaveri | January 10, 2008 | Reply

  2. …but I don’t see anything in here that would make the pop up behave modally. I see that you try to make it look pretty by reducing the opacity, but that’s purely cosmetic. In fact, I tried your sample and the pop up is not modal, i.e., we can still select other commands from the menu, click on other buttons, etc.

    Comment by Kevin Le | March 3, 2008 | Reply

  3. Kevin, that is why I use the words “Modal-like”. This particular example is using a user control as a Modal-like window. If you need a true modal dialog, simply put your user control in a form and display as showdialog.

    Comment by roecode | March 3, 2008 | Reply

  4. Thanks for your reply. Good exercise for me to go through.

    Comment by Kevin Le | March 3, 2008 | Reply

  5. Complete source code note included?

    Comment by A.V.Ebrahimi | May 18, 2008 | Reply

  6. No the complete source code for this project is under a NDA. What is shown here is more than enough to demonstrate the Modal Dialog popup concept. I would be happy to discuss specific questions you might have on the topic, but no I will not be releasing the project source code.

    Comment by roecode | May 19, 2008 | Reply

  7. Hi guys!

    About the “modal” / “blocking” behavior: I had the same problem and solved it using a small “hack” to make the whole thing blocking.

    You can read in my blog and download the small sample here: http://blog.technewlogic.de/post/WPF-Modaler-Dialog-(sync-async).aspx

    Comment by Ronald | April 22, 2009 | Reply

  8. Thank you, it’s very helpful. I’ve been looking for how to access custom user control’s methods but in vain, until I found yours.

    Comment by naughtykid | May 24, 2009 | Reply

    • Glad it was helpful.

      Comment by roecode | May 26, 2009 | Reply

  9. This was VERY helpful. Thanks!
    I have a couple of questions:
    1) Where should I declare the user control in my consumer Window?
    2) How can I make the user control be invisible in design-time. When I am working on my consuming Window I do not want to see the dialog user control.
    Thanks a lot!!!

    Comment by Gus | February 4, 2010 | Reply

  10. I’m developing a custom control that must show modal dialogs and needs to be used from other technologies (Application.Current.MainWindow will return null). In the UserControl, if you call ShowDialog() everithing seems to be OK, but if you try to position this window using PointToScreen you get the following error: “This Visual is not connected to a PresentationSource”. Do you know any way to set the window owner for the modal dialog to the host window (not a wpf window in my case)?.

    Comment by crusjiber | September 23, 2010 | Reply

  11. Why not just use nested message pumps to create modal controls

    http://www.deanchalk.me.uk/post/WPF-Modal-Controls-Via-DispatcherFrame-%28Nested-Message-Pumps%29.aspx

    Comment by Dean Chalk | November 12, 2010 | Reply


Leave a reply to Kevin Le Cancel reply