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!