Using Popup to create a Dialog class

Presenting a dialog to the user is a common task for many applications. Silverlight 2 does not have a Dialog class, but it is possible to use the Popup class to create a very credible dialog. My Dialog class can’t leave the Silverlight plugin–for that you would have to use Javascript interop to create a new Silverlight plugin, etc. and that’s a topic for somebody else’s blog 🙂

The key here is to make the Popup full screen (and resize it when the plugin size changes) and also have a Canvas that is full screen. Then, if you want to have a modal dialog, set the Canvas’s Background property. This will prevent mouse interaction with the rest of your application. This will also enable you to detect when the user clicks outside of your dialog content, in case you want to dismiss the dialog that way.  

The one caveat that I can think of is that keyboard events can still follow the focus, which can be set to elements beneath the modal dialog. I have some ideas how to fix this in the RTM timeframe.

To use the Dialog class, you will need to subclass it, and provide an override for the GetContent method. The content that you provide will become centered (in a Grid) on the screen.

Here is the code for the Dialog class:

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Controls.Primitives;

using System.Windows.Media;

using System.Windows.Shapes;


namespace DialogApp


    public abstract class Dialog


        public void Show(DialogStyle style)


            if (_isShowing)

                throw new InvalidOperationException();


            _isShowing = true;




            _popup.IsOpen = true;


            Application.Current.Host.Content.Resized += OnPluginSizeChanged;



        public void Close()


            _isShowing = false;


            if (_popup != null)


                _popup.IsOpen = false;

                Application.Current.Host.Content.Resized -= OnPluginSizeChanged;




        // Override this method to add your content to the dialog

        protected abstract FrameworkElement GetContent();


        // Override this method if you want to do something (e.g. call Close) when you click

        // outside of the content

        protected virtual void OnClickOutside() { }


        // A Grid is the child of the Popup. If it is modal, it will contain a Canvas, which

        // will be sized to fill the plugin and prevent mouse interaction with the elements

        // outside of the popup. (Keyboard interaction is still possible, but hopefully when

        // Silverlight 2 RTMs, you can disable the root to take care of that.) The Grid isn’t

        // strictly needed if there is always a Canvas, but it is handy for centering the content.


        // The other child of the Grid is the content of the popup. This is obtained from the

        // GetContent method.


        private void EnsurePopup(DialogStyle style)


            if (_popup != null)



            _popup = new Popup();

            _grid = new Grid();

            _popup.Child = _grid;


            if (style != DialogStyle.NonModal)


                // If Canvas.Background != null, you cannot click through it


                _canvas = new Canvas();

                _canvas.MouseLeftButtonDown += (sender, args) => { OnClickOutside(); };


                if (style == DialogStyle.Modal)


                    _canvas.Background = new SolidColorBrush(Colors.Transparent);


                else if (style == DialogStyle.ModalDimmed)


                    _canvas.Background = new SolidColorBrush(Color.FromArgb(0x20, 0x80, 0x80, 0x80));






            _grid.Children.Add(_content = GetContent());





        private void OnPluginSizeChanged(object sender, EventArgs e)





        private void UpdateSize()


            _grid.Width  = Application.Current.Host.Content.ActualWidth;

            _grid.Height = Application.Current.Host.Content.ActualHeight;


            if (_canvas != null)


                _canvas.Width = _grid.Width;

                _canvas.Height = _grid.Height;




        private bool _isShowing;

        private Popup _popup;

        private Grid _grid;

        private Canvas _canvas;

        private FrameworkElement _content;



    public enum DialogStyle








Here is how I use it in my sample:

<UserControl x:Class=”DialogApp.Page”




    <Border x:Name=”LayoutRoot” Background=”White”>

        <StackPanel Margin=”8″ Width=”120″ VerticalAlignment=”Top” HorizontalAlignment=”Left”>

            <Button Height=”24″ Margin=”2″ Content=”Show Popup” Click=”Button_Click”/>

            <RadioButton Height=”24″ Margin=”2″ Content=”Non-Modal” IsChecked=”true”/>

            <RadioButton Height=”24″ Margin=”2″ x:Name=”isModal” Content=”Modal”/>

            <RadioButton Height=”24″ Margin=”2″ x:Name=”isModalDimmed” Content=”Modal Dimmed”/>





using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;


namespace DialogApp


    public partial class Page : UserControl


        public Page()





        private void Button_Click(object sender, RoutedEventArgs e)


            Dialog dlg = new MyDialog();

            if (isModal.IsChecked.Value)


            else if (isModalDimmed.IsChecked.Value)







    public class MyDialog : Dialog


        protected override FrameworkElement GetContent()


            // You could just use XamlReader to do everything except the event hookup.


            Grid grid = new Grid() { Width = 200, Height = 200, };

            Border border = new Border() { BorderBrush = new SolidColorBrush(Colors.Black), BorderThickness = new Thickness(2), CornerRadius = new CornerRadius(4), Background = new SolidColorBrush(Colors.White) };


            grid.Children.Add(new TextBlock() { Text = “Dialog”, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top, Margin = new Thickness(8) });

            Button button = new Button() { Width = 50, Height = 24, Content = “Close”, HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Bottom, Margin = new Thickness(8) };


            button.Click += (sender, args) => { Close(); };


            return grid;



        protected override void OnClickOutside()








Comments (14)

  1. Mark Rideout says:

    You should set TabNavigation=Cycle for your user control so the user doesn’t tab outside it on the modal cases.


  2. schmiddy says:

    What if you need to design your dialogs in xaml rather than coding everything up in C# in the GetContent() method?

    This may be important if you have lots of complex dialogs that designers create in Blend.

  3. schmiddy – In that case, you can make the dialog subclass return a new UserControl subclass for its content–and design the UserControl subclass as normal.

  4. maxchristian says:

    This doesn’t work on 2.0 RTW if the content is non-trivial, e.g. try adding a ListBox inside the dialog and clicking on it a few times — you get "System Exception: Catastrophic failure".

    I’ve found that doing LayoutRoot.Children.Add(_popup) sorts it, not quite sure of the implications of that though.

  5. maxchristian, yes, anything that calls TransformToVisual under the hood will crash unless you do what you suggest.

    The implications are that the popup will be affected by the RenderTransforms that apply to the LayoutRoot, but if you are a little clever you can also get around that if need be.

  6. maxchristian says:

    Ah, so that’s why my dialog became enormous when I made the SL control fill the browser window using a RenderTransform…

    Can you be more specific?  I’m not sure if I’m a little clever but I’m certainly a little lazy.  😉

  7. maxchristian,

    You may need to change where you put the RenderTransforms, and/or add an additional element. If you had this:


       <Grid Name=LayoutRoot>

    and the RenderTransforms were on the UserControl or the Grid, and you added the Popup to the Grid, then you may need to do something like this:


       <Grid Name=newRoot>

           <Grid Name=LayoutRoot>

    Add the newRoot Grid, put the RenderTransforms on the LayoutRoot, and add the Popup to the newRoot.

  8. kobruleht says:

    How to allow to use tab and left/right arrow keys to navigate between buttons ?

    Currently keyboard naviation is not available.

    Also, zip file dowload link is broken.


  9. tearaway_Tea says:

    Thanks. This is a great class!

  10. kpinckert says:

    I am unable to put a ComboBox on a UserControl that is used for a popup window.  When I popup the control and touch the ComboBox it hangs.  It can be empty or not. Using SL2.  Please advise.  Thank you.

  11. This is likely due to an SL2 bug. ComboBoxes in a Popup, when the Popup is not in the visual tree (i.e. in the page’s XAML) don’t work. This has been fixed for SL3.

  12. kpinckert says:

    Ok, thanks.  A work around then is to wrap your ComboBox in another UserControl in some way; it just can’t sit directly on the popup control.  I tried that  and  it seems to be working.

    Thanks for the help.

  13. Silverlight Tech says:


    I find it useful even there is ChildWindow in Silverlight 3 now. ChildWindow is difficult to tune when it provides FullScreen button.

  14. Silverlight Tech says:

    Also it should call UpdateSize() method in Show() method too because user can change the browser size while popup is closed.