Sunday, November 9, 2008

Using the popup element in Silverlight

It's been a while, as I was realy busy with getting our latest project of the ground, but finally here we are again.

This time, I wanted to look into the use of the popup element, as I plan on using this in future applications to handle some basic use cases. One of those is displaying a message to the user, for example an error message.

I started out with a simple application containing a grid as this is what most of my applications look like. As I wanted my popup to center in the browser window I added a canvas to the top left cell of the grid (in my case that would be the top row). Then I spanned the canvas trough all the rows and columns, so I covers the entire window. My xaml looks like this:


<grid name="LayoutRoot" background="White">
<grid.rowdefinitions>
<rowdefinition height="100">
<rowdefinition height="*">
<rowdefinition height="100">
</Grid.RowDefinitions>
<textblock row="0" margin="10" fontsize="20">Errorbox demo</textblock>
<button row="1" content="Throw error!" margin="20" click="Button_Click">
<textblock row="2" margin="10" verticalalignment="Bottom">Click the button to see a Popup control in action</textblock>
<canvas name="rootCanvas" row="0" rowspan="3">
</canvas>
</grid>


Next step is to actually build the popup for displaying error messages. It's as simple as wrapping any xaml you want for your popup inside a popup element. If you use Blend, like I do, what you may notice is that it doesn't display the popup by default. To have it displayed, you have to select the popup in the Objects and Timeline window. It then shows you the popup and it's contents.

The xaml for the popup looks like this:


<Popup x:Name="errorPopup">
<Border Background="#FFFFFFFF" BorderBrush="#FF000000" Height="300" Width="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="15" />
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Border Grid.Row="0" CornerRadius="15,15,0,0">
<TextBlock x:Name="TitleTextBlock"></TextBlock>
</Border>
<TextBlock Grid.Row="1" x:Name="ErrorText"></TextBlock>
<Border Grid.Row="2" CornerRadius="0,0,15,15">
<Button x:Name="OkButton" Width="100" HorizontalAlignment="Right" Margin="5" Content="Ok" Click="OkButton_Click"></Button>
</Border>
</Grid>
</Border>
</Popup>

So now we can write some code to popup our message. One thing that got me googling was how to actually show the popup. You use the IsOpen property which is a boolean. My code for displaying the popup looks like this:


public static void PopupError(Exception error, Canvas parent)
{
ErrorBox errorBox = new ErrorBox();
errorBox.Error = error;
parent.Children.Add(errorBox);
Canvas.SetLeft(errorBox, (parent.ActualWidth / 2) - errorBox.Width / 2);
Canvas.SetTop(errorBox, (parent.ActualHeight / 2) - errorBox.Height / 2);

errorBox.errorPopup.IsOpen = true;
}


When you want your popup to close, simply set the IsOpen property to false again. Note the use of the ActualHeight and ActualWidth. These are important because these are the dimensions that where set after rendering instead of the Height and Width property that are set in design mode. Another thing that you may run into is that these are set to 0. in the Loaded event of the page AND also in the Loaded event of the Canvas. If you rely on these events some redesinging is required to get this to work.

You can now download the project here. It's not all polished up, but you'll get the picture.

By the way, please let me now what you think about my blog and if there are any topics you would like to read about.

4 comments:

  1. Nice Article , thank you though.
    If you want to block about a real headcracker, try to implement a duplex polling service which is awrare of connection pair loose. This would be great !

    ReplyDelete
  2. Hi Lars,

    Thanks for your feedback. I won't be writing about this, sorry.
    Dan Wahlin has written a great article about a duplex WCF service implementation for SL2, including source. You can find it here.
    If you want to detect the loss of a client in this setup, you catch an exception from sending a message to the client. I've tested this in an IIS setup and it works great. If you have any questions, please let me know.

    ReplyDelete
  3. Thanks for the article is it possible to post the sample project ?
    Thanks
    Sach

    ReplyDelete
  4. Hi Sachin,

    Good idea. I've added a link, so you can download the sample project.

    Greets,
    Jonathan

    ReplyDelete