Silverlight 3's New Child Windows

25 Comments April 29, 2009


If you've worked with Silverlight 3, you may have noticed that Visual Studio's Add New Item dialog includes an option for adding a "Silverlight Child Window" to your Silverlight project:

Silverlight Child Window

The new child window feature makes it easy to add modal dialogs to Silverlight applications. A child window derives from the new ChildWindow class, and its content is defined in XAML (of course!). So you can now embellish an application with modal popups containing rich content.

To see this feature in action, create a new Silverlight project and add a Silverlight child window to it. Replace "ChildWindow1.xaml" in the Name box with "ErrorDialog.xaml" and click OK. Visual Studio responds by adding two new files to your project: ErrorDialog.xaml, which contains the child window's UI, and ErrorDialog.xaml.cs, which contains the child window's code-behind class. You can display your new child window with two simple lines of code:

ErrorDialog dlg = new ErrorDialog();

dlg.Show();

When you do, an empty dialog appears with OK and Cancel buttons at the bottom. The content behind the dialog grays out and the user has to dismiss the dialog before doing anything else in the application.

You can add content to the dialog by declaring the content in ErrorDialog.xaml. You can also remove the OK and Cancel buttons by deleting the Button declarations. Here's some content you can plug into ErrorDialog.xaml to customize the dialog's appearance:

<StackPanel Orientation="Vertical">

  <Image Source="Images/UnhappyFace.png" Stretch="None" Margin="8" />

  <TextBlock Text="An unforeseen error has occurred. Please contact a system administrator or, better yet, use our competitor's Web site until we get the problem resolved." TextWrapping="Wrap" />

</StackPanel>

<Button x:Name="CloseButton" Content="Close" Click="CloseButton_Click"

  Width="75" Height="23" HorizontalAlignment="Center" Margin="16"

  Grid.Row="1" />

Add the following line of code to ErrorDialog's constructor to customize the title bar:

this.Title = "Error";

And add the following method to the ErrorDialog class to handle clicks of the Close button:

private void CloseButton_Click(object sender, RoutedEventArgs e)

{

    this.DialogResult = false;

}

When you display the dialog, here's what you get:

Child Window 

It's not earth-shaking, but it's certainly nice to have the ability to dress up your apps with genuine modal dialogs.

This is all rather straightforward, but certain aspects of a child window's operation merit further explanation. For example, the ChildWindow class has a Close() method that you can call to close a dialog, but my CloseButton_Click handler, which is patterned after the click handlers provided by Visual Studio, doesn't call it. DialogResult's setter calls Close for you, so simply assigning a value to the DialogResult property is sufficient to close the dialog.

Another aspect of child windows that may not be obvious is that Show() is an asynchronous call. That is, it doesn't wait for the dialog to be dismissed; it returns immediately. That's why Show() returns void rather than a DialogResult. If you want to know how the dialog was dismissed (that is, what the DialogResult value is once the dialog is closed), you handle the dialog's Closed event and check DialogResult there:

ErrorDialog dlg = new ErrorDialog ();

dlg.Closed += new EventHandler(OnErrorDialogClosed);

dlg.Show();

  ...

private void OnErrorDialogClosed(object sender, EventArgs e)

{

    ErrorDialog dlg = (ErrorDialog)sender;

    bool? result = dlg.DialogResult;

}

Note that DialogResult is a nullable bool, so it isn't necessarily set to true or false.

One last item to consider is how to retrieve input from a child window that allows the user to input data. Generally you build public properties into the dialog class and transfer values from the dialog's input controls into these properties in the OK button's click handler. After the dialog is dismissed, you then retrieve the user input from the dialog properties. For example, suppose a child-window class named InputDialog contains a TextBox named "InputBox" so the user can enter text. You could do this in the dialog class:

public string Input { get; set; }

  ...

private void OKButton_Click(object sender, RoutedEventArgs e)

{

    this.Input = InputBox.Text;

    this.DialogResult = true;

}

And after the dialog is dismissed, you could do this to find out what the user typed into the TextBox:

private void OnInputDialogClosed(object sender, EventArgs e)

{

    InputDialog dlg = (InputDialog)sender;

    bool? result = dlg.DialogResult;

 

    if (result.HasValue && result.Value)

    {

        string input = dlg.Input;

    }

}

This is how we used to retrieve input from dialog boxes in MFC. And now, 15 years later, it comes in handy again. I guess useful patterns never die!


25 Comments

  • Gravatar Image
    David Tosi April 29, 2009 10:41 PM

    I had to write a very similar function for SL2 - can't wait to kick SL3's wheels. Can the window leave the scope of the browser (or application in the case of an out-of-browser scenario?) Or will it still be confined to the primary grid/canvas? Thanks!

  • Gravatar Image
    jprosise April 29, 2009 11:45 PM

    It's still confined. Sigh.

  • Gravatar Image
    JasonBSteele April 30, 2009 1:06 PM

    I really hope that its not confined by the time its released - it makes it worthless I will have to continue with my hack using the bridge to javascript.

    Also it would be good to have other window modes - e.g. always on top, modeless.

  • Gravatar Image
    ILang June 11, 2009 6:30 PM

    Is it possible to change the behavior of the ChildWindow the way it opens and closes? It kind of jumps out at you and disappears just as dramatically. I don't think this effect is appropriate in the business application when you open hundreds of windows a day.

  • Gravatar Image
    Christian Wirth June 23, 2009 10:14 AM

    Nice! That was overdue!

  • Gravatar Image
    Fred July 3, 2009 7:08 PM

    Thanks!! Very Usefull

  • Gravatar Image
    Amar July 28, 2009 5:50 AM

    Very Good Article!

  • Gravatar Image
    DotNetKicks.com August 4, 2009 4:27 PM

    You've been kicked (a good thing) - Trackback from DotNetKicks.com

  • Gravatar Image
    John August 20, 2009 12:59 PM

    Is there a way to get a ChildWindow and/or its buttons to respond to an Escape keypress (for a Cancel button) and to respond to an Enter keypress (for an OK button)?

    Thank you in advance, and thanks for writing the article.

  • Gravatar Image
    Roy September 6, 2009 4:19 AM

    John, You can always refactor the control itself..
    Take a look at tims page:
    http://timheuer.com/blog/archive/2009/05/10/silverlight-childwindow-non-modal-refactor.aspx


    /Roy

  • Gravatar Image
    harisha September 24, 2009 1:04 PM

    Hi I want to open a PDF document in the child window, can this be done?? I mean the child window when popped up will have only the PDF document that can be scrolled vertically.

  • Gravatar Image
    Michal September 27, 2009 3:28 PM

    Hi!
    Great Article!

    I was wondering how one can access resource files in the child window class?

    Im able to access it normally through a page in the xaml by using the tag but it doesnt work in a child window and I need it for localization.

    Thanks!

  • Gravatar Image
    brian October 26, 2009 4:46 PM

    excellent article, exactly what i was looking for. thx!

  • Gravatar Image
    marcelo December 15, 2009 12:47 AM

    thank so much! very helpful article!

  • Gravatar Image
    Jemson Sentillas January 17, 2010 11:55 PM

    Very useful article!
    Thanks

  • Gravatar Image
    Ghulam Haider February 2, 2010 2:45 AM

    Excellent shortest trick. Bundle of thanks...

  • Gravatar Image
    MAS100 February 10, 2010 11:16 PM

    I gotta do this in Silverlight XAML VB! How do i open the child window in VB?

  • Gravatar Image
    Ivan March 23, 2010 10:46 AM

    Thx! Really helpfull post!
    "One last item to consider is how to retrieve input from a child window that allows the user to input data."
    private void OnInputDialogClosed(object sender, EventArgs e)
    {
    InputDialog dlg = (InputDialog)sender;
    bool? result = dlg.DialogResult;
    if (result.HasValue && result.Value)
    {
    string input = dlg.InputBox.Text; //it's work too
    }
    }

  • Gravatar Image
    78th Place May 7, 2010 10:19 AM

    Silverlight ChildWindow / Modal Dialog 101

  • Gravatar Image
    k3nn November 23, 2010 11:09 PM

    is there a busyIndicator for childwindows to use?

  • Gravatar Image
    Ismail (isozworld) February 7, 2011 10:32 AM

    Thank you very much for your great post Jeff.

  • Gravatar Image
    trajce April 1, 2011 10:44 PM

    Thanks a lot.
    i was stuck for hours till trying to figure out whats wrong with my code, until i read here that Show() is an asynchronous call.

  • Gravatar Image
    Tadej May 26, 2011 6:23 AM

    Hi, is there a way to call the child window in synchronous way?

    Regards

  • Gravatar Image
    Abc July 14, 2011 8:51 AM

    http://www.wintellect.com/CS/bhttp://www.wintellect.com/CS/blogs/JpegImage.aspxlhttp://www.wintellect.com/CS/blogs/JpegImage.aspxogs/JpegIhttp://www.wintellect.com/CS/blogs/JpegImage.aspxmaghttp://http://www.wintellect.com/CS/blogs/JpegImage.aspxhttp://www.wintellect.com/CS/blogs/JpegImage.aspxwwhttp://www.winthttp://www.wintellect.com/CS/blogs/JpegImage.aspxellect.com/http://www.wintellect.com/http://www.wintellect.com/CS/blogs/JpegImage.aspxCS/blogs/JpegImage.aspxCS/blogs/Jphttp://www.wintellect.com/CS/blogs/JpegImage.http://www.wintellect.com/CS/blogs/JpegImage.aspxaspxegImage.aspxhthttp://www.wintellect.com/CS/blogs/JpegImage.aspxtp://www.htthttp://www.wintellect.com/CS/blogs/JpegImage.aspxp://www.wintellect.com/CS/blogs/JpegImage.aspxwintellect.com/CS/blogs/JpegImhttp://www.wintellect.com/CS/blogs/JpegImage.aspxage.aspxw.http://www.wintellect.com/CS/blogs/JpegImage.aspxwintellhttp://www.wintellect.com/CS/blogs/JpegImage.ahttp://www.wintellect.com/CS/blhttp://www.wintellect.com/CS/blogs/JpegImage.aspxogs/JpegImage.aspxspxecthttp://www.winhttp://www.wintellect.com/CS/blogs/JpegImage.aspxtellect.com/CS/blogs/JpegIhttp://www.wintellect.com/CS/blogs/JpegImage.ahttp://www.wintellect.com/CS/blogs/JpegImage.aspxspxmaghttp://www.wintellect.com/CS/blogs/JpegImage.aspxe.aspx.com/CS/http://www.wintellect.com/CS/blogs/JpegImage.aspxblogs/Jpeghttp://www.wintellect.com/CS/blogs/JpegImage.aspxImage.ashttp://http://www.wintellect.com/CS/blogs/JpegImage.aspxwhttp://www.wintellect.com/CS/blogs/JpegImage.aspxww.wintellect.com/CS/blogs/JpegImage.aspxphttp://wwhttp://wwhttp://www.wintellect.cohttp://www.wintellect.com/CS/blogs/JpegImage.aspxm/CS/blogs/JpegImage.ahttp://www.wintellect.com/CS/blogs/JpegImage.aspxspxw.wintellect.com/CS/blogs/JpegImage.aspxw.wintellect.com/CS/bloghttp://www.wintellect.com/CS/blogs/JpegImage.aspxs/JpegImage.aspxxe.aspxhttp://wwhttp://www.wihttp://www.wintellechttp://wwwhttp://www.wintellehttp://www.wintellect.com/CS/blogs/JpegImage.aspxct.com/CS/blogs/JpegImage.aspx.wintellect.com/CS/blogs/JpegImage.aspxt.com/CS/blogs/JpegImage.aspxnhttp://whttp://www.wintellect.http://www.wintellect.com/CS/blogs/JpegImage.aspxcom/CS/blogs/JpegImage.aspxww.wintellect.com/CS/blogs/JpegImage.aspxtehttp://www.wintellect.com/CS/blogs/JpegImage.aspxllect.com/CS/blogs/http://www.wintellect.com/CS/blhttphttp://www.winthttp://www.wintellect.com/CS/blogs/JpegImage.aspxellect.com/CS/blogs/JpegImage.aspx://www.wintellect.com/CS/blogs/JpegImage.aspxogs/JpegImage.aspxJphttp://www.wintellect.com/CS/blogs/JpegImage.aspxegImage.aspxw.wintellect.com/http://www.wintellect.cohttp://whttp://www.wintellect.com/CS/blogs/JpegImage.aspxwhttp://www.wintellect.com/CS/blogs/JpegImage.aspxw.wintellect.com/CS/blogs/JpegImage.aspxm/CS/blogs/JpegImage.aspxCS/blogs/JpegImahttp://www.winhttp://www.wintehttp://www.wintellect.com/CS/blogs/JpegImage.aspxllect.com/CS/blogs/JpegImage.aspxtellect.cohttp://www.wintellect.com/CS/blogs/JpegImage.aspxm/CS/blogs/JpegImage.aspxge.aspxhttp://wwwhttp://www.wintellect.com/CS/blogs/JpegImage.aspx.wintellect.com/CS/blogs/JpegImage.aspxhhttp://www.wintellect.com/CS/blogs/JpegImage.aspxttp://www.wintellect.com/CS/blogs/JpegImage.aspxhttp://www.wintellect.com/CS/blogs/JpegImage.aspxhttp://www.wintellect.com/CS/blogs/JpegImaghttp://www.wintellect.com/CS/blogs/JpegImage.aspxe.aspxhttp://www.wintellect.com/CS/blogs/JpegImage.aspxhttp://www.wintelhttp://www.wintellect.com/CS/blogs/JpegImage.aspxlect.com/CS/blogs/JpegImage.aspxhttp://www.wintellect.com/CS/blogs/JpegImage.aspxhttp://www.wintellect.com/CS/blogs/JpegImage.aspxhttp://www.wintellect.com/CS/blogs/JpegImage.aspxhttp://www.wintehttp://www.wintellect.com/CS/blogs/JpegImage.aspxllect.com/CS/blogs/JpegImage.aspxhttp://www.wintellect.com/CS/blogs/JpegImage.aspx

  • Gravatar Image
    keswin May 12, 2012 10:28 AM

    nada q quiero misica para virtual dj

Have a Comment?

Archives

Tags

Blogs