Introduction

In this article, I'll show you how to create a custom messagebox user control in Silverlight 3, so that you can use it in any Silverlight application instead of the default messagebox.

Background

In order to be able to complete this tutorial, you should know a little about Microsoft Expression Blend, which we are going to use in creating the MessageBox user control. I assume that you are familiar with Expression Blend and with its UI.

Basic Idea

There's no doubt that the messagebox control is used massively in any application whatever it was desktop or web as you may need to ask the user for something, warn him for some dangerous operations, or just display an information to the user, and so on... The control must be very flexible to handle all of these scenarios. Moreover, it must be a modal dialog which prevents users from accessing the background of the page until the dialog is closed.

Creating the MessageBox User Control

Start Expression Blend and choose Control library project template (in order to generate a DLL so that it can be added to in any Silverlight application), then remove the MainControl user control from your solution and add a new Child Window. This child window will be opened as a modal dialog, so we are now ready for changing the style of the child window and make it look like the screen shot.

Designing the MessageBox

In Objects and timeline panel, right click on the ChildWindow node, then choose Edit Template, then Edit a Copy. Now we will be able to customize the layout of the child window to meet our requirements. You will realize that the 5th Border is the most important one that includes all the UI elements.

Expand the 5th border control and choose the Chrome node; the Chrome node is the header of the messagebox, so we are going to change its background color using the gradient brush using the following XAML code:

After finishing the header style, we are going to add a background image to give it a better appearance, so add an image in the grid that hosts the chrome element, or you can just adjust the background color of that grid, so it's up to you.

Adding Controls for the MessageBox

At this point, we have finished styling our custom messagebox layout, but we want to display the text message and add some buttons to the body of the messagebox, so back to the childwindow we are going to add the following items:

Textblock element in order to display the text message to the user.

Image element that displays the icon of the message according to the user choice.

butto3 - 3 buttons (Yes, No, & Cancel), but the user may want to display just only 2 buttons (Yes & No) or may be just one (Ok), so we are going to group them into a StackPanel in order to keep them centered in the dialog.

So the final UI tree should look like this in the Objects & timeline panel:

Adding Some Options for the User

So far we've finished all the design work for the user control, so let's add some options for the user. We are going to add two enums in our namespace (MessageBoxButtons & MessageBoxIcon), in order to enable the user to select the correct message type, for example he/she may want to display an error message, so we should display the error icon in the message.

Getting the messagebox Result

One last thing we want to know is which button was clicked by the user, so what about making a public method Show(string message, string title); that returns the DialogResult exactly like the messagebox class in the Windows Forms? Unfortunately this is not applicable in Silverlight, because in windows forms the messagebox waits for a response from the user so that the program can complete processing, but this is not the same case in Silverlight. The modal dialog will be opened and the rest of code will be executed as well, so the application is not waiting for the user to close the dialog in order to complete its work. In order to overcome this issue, we are going to handle the close event of the messagebox control so that we can know the clicked button.

I declared a delegate function with one parameter of type MessageBoxResult in order to know which button was clicked.

//delegate to get the selected MessageBoxResultpublicdelegatevoid MessageBoxClosedDelegate(MessageBoxResult result);
//event will be fired in the Close event of the usercontrolpublicevent MessageBoxClosedDelegate OnMessageBoxClosed;
//property to keep the result of the messageboxpublic MessageBoxResult Result { get; set; }

Handling the Close Event

How To Use

First you will need to add the generated DLL from this class library to any Silverlight application. The child window class has a public method called "Show()" so we are going to use it for opening the messagebox, but we want to set its title, text message, icon & number of buttons according to user choices; so we can send these parameters whether through a public method or through an overload for the constructor, I chose the 2nd option and created another overload for the default constructor and passed the parameters through it, so use the following code to open the messagebox:

//displayed messagestring msg = "An error has occurred and the operation was cancelled,
Are you sure you want to continue?";
//creating new instance from the MessageBoxControl
MessageBoxControl.MessageBoxChildWindow w =
new MessageBoxControl.MessageBoxChildWindow("Error", msg,
MessageBoxControl.MessageBoxButtons.YesNo,
MessageBoxControl.MessageBoxIcon.Error);
//define the close event handler for the control
w.OnMessageBoxClosed +=
new MessageBoxControl.MessageBoxChildWindow.MessageBoxClosedDelegate
(w_OnMessageBoxClosed);
//open the message
w.Show();

Final Word

I've attached a test application that displays the messagebox dynamically, so that you can test all of its capabilities.

I couldn't figure out the difference between my way and the way you mentioned in your link, it's the SAME, first you create an object of the messagebox control, then wire up an event then call the show method oh man they are the same steps!!
anyway thanks for voting

No my project is very similar to yours - almost exactly the same. The only difference that I offer are easy integration with existing projects and simplicity of use. So all that a user has to do is download a simple dll file and use it. That's all - and maybe, I have different design than yours.

The MessageBox.Show method does not return until the user dismisses the dialog. The UI thread that calls ChildWindow.Show keeps on going. So, if you need to ask the user to confirm an action this approach won't work.

simply you are going to check the result parameter passed in the OnMessageBoxClosed event handler then type in your code based on that parameter, the only difference between this approach and windows forms approach is you are going to implement your confirmation code in the OnMessageBoxClosed event handler, so both results are equal.

In cases where you need a synchronous call to Show() so that you can do something with the results like respond to a CancelEventArgs, have you done any work on this? I assume it means creating a helper that deals with the SL message pump.
thanks
Marty

actually I was looking for a synchronous call to Show() method and I failed, but we can make a work arround to solve this issue:
you can use the Closing event instead of Closed event so you will be able to use the CancelEventArgs parameter and you may pass it to another method or another event to handle it in different ways

First let me explain to you what is meant by w.OnMessageBoxClosed+=new MessageBoxControl.MessageBoxChildWindow.MessageBoxClosedDelegate(w_OnMessageBoxClosed);

OnMessageBoxClosed is called an event, and each event should have a handler method that is executed after the event has been fired, so what we want to do is just linking the event to it's handler method, and in this case the handler method is w_OnMessageBoxClosed and its type is MessageBoxClosedDelegate

so the value that should be passed to the w_OnMessageBoxClosed parameter is the handler method that is going to handle your closing event of the messagebox window, so if you are using Microsoft Visual Studio it will create this method automatically for you, but if you don't you can copy this method and paste it into your code file

Hi,
the w_OnMessageBoxClosed is used to execute additional codes when the dialog is confirm or cancel.
How about if we need to pass parameters which are necessary for the additional code?
Any other ways except set the variables as private and access directly?
For example
private void A(string a, string b, object c)
{
//Code
//Show message box
//Additional code which used a, b and c. Move to onclosed event.
}

private void B(MessageBoxResult)
{
// Get result
// Execute additional code. How do we use a, b and c ?
}

you can use the private variables as you mentioned, or you can define properties in the MessageBox object, and set them in your method
private void A(string a, string b, object c)
{
msgBoxObj.a = a;
msgBoxObj.b = b;
msgBoxObj.c = c;
}

so you can access them in the closing method, and I do recommend you to keep the messagebox control as it is, because it has one purpose which is displaying messageboxes to the user

First I'm so sorry for my late reply, but I've just realized your message right now.
Second in order to change the title back color you should follow these steps using MS Expression Blend
1- Open the project source
2- in the objects and timeline panel right click on ChildWindow Node and choose Edit template, then Edit Current.
3- expand ContentRoot node and then expand the Last Border node too.
4- expand all the children UI elements from that Border node until you find a UI element called Chrome, this is the title UI element, so you will be able to change it's back color as you want.