Introduction
Do you work with Child Windows in Silverlight and want to customize the look & feel to match with your application UI? Then this post will help you to understand the process. I am going to discuss with you the customization steps in detail, so that next time when you want to modify your Child Window UI, you will find it very useful.
In this article, I will guide you through the steps of customization with the help of a sample application. We will need Microsoft Expression Blend for the full customization. Read the complete article to learn about it.
Setting up the Basic Project
Open your Expression Blend and create a new "Silverlight Application" project by specifying proper name, location and target version. Click "OK" and the IDE will create the Silverlight project for you.
Once your project is ready, select the LayoutRoot
and from the toolbox, click the dropdown arrow as shown in the below screenshot:
This will open the search toolbox tab for you. Search for the "ChildWindow
" and select it. Note that the ChildWindow
is part of the System.Windows.Controls.dll assembly.
Now draw the ChildWindow
inside the LayoutRoot
Grid as shown in the below screenshot:
It will add the ChildWindow
inside your XAML page. Resize it properly, so that, it will look good when you run the application.
Now let's run the application and have a look into the default Child Window. It doesn't look good, right? Yes, it is the default look of the Silverlight ChildWindow
. Now, we need to customize it by editing the template of the control.
Editing the ChildWindow Template
Let's open the Blend IDE and write click on the ChildWindow
control under the objects tab. From the context menu, select the "Edit Template" and from the 2nd level context menu, click on the "Edit a Copy..." menu item.
Remember that for the first time, you have to click on the "Edit a Copy..." menu item. But, once you return to this screen and want to customize the existing template, you have to click on the "Edit Current" menu item.
This will open the "Create Style Resource" dialog in your screen. Give a proper name to your new style and choose where to store the style resource. Now click "OK" to start modifying the template.
You will see the following template inside your Blend IDE, which consists of several Border controls and Grid. It has some additional controls too. We will now discuss them so that you can understand it properly and in future you will find it very easy to customize.
Inside the Root
grid, we have two more Grids named "Overlay
" and "ContentRoot
". Overlay
grid control actually creates the semi transparent background which makes the ChildWindow
as modal dialog. Modal dialog means, you will not able to click on any controls outside when the Child Window is open.
The ContentRoot
Grid has 5 different Border controls. The first four Border controls are used to create the border shade of the Child Window. If you want to change the shade of the Window, you can modify those accordingly.
For now, we are not worried about the shades. We will customize the other part of the Window.
If you expand the fifth Border control, you will see several levels of Grid and Border controls inside it.
As shown in the below snapshot, you will see that, there are two Borders inside the selected Grid. The Grid control has two rows. In the first row, we have one border control named "Chrome
". This is the title bar of your Child Window.
Don't want to change the name of the border named "Chrome
". If you rename it or delete it, you will not be able to drag the Child Window inside your application UI.
In the second row, we have the actual content placeholder to show any content inside the Window.
Modifying the Style
Select the Border control named "Chrome
". Now from the properties panel, change the Background color as per your requirement. Give a gradient brush to your title bar.
Expand the Chrome control and select the CloseButton
which is placed inside the title bar. Set a bigger size to it by specifying the height and width of the button. Set the cursor type to "Hand
".
You can also change the Close Button template. As you did for the Child Window, right click on the CloseButton
control. You will see that the "Edit Current" submenu item of "Edit Template" is enabled. It means that the style is already available and you don't have to create it from scratch.
Click "Edit Current" and it will open the template of the button into the screen.
As shown in the below screenshot, select the path control labelled "X" and set its height & width. You can also change the color and other look and feel of the close button from this screen. You can also add some animations for states to it for the mouse over or pressed state.
Now you can change the look & feel of the content control, which holds the title of the Child Window.
Select the main border control of the Content Control and give background color to it, as per your UI style. Set a different Foreground color to match the title with the bar background.
Run the application and you will see a nice UI for the Child Window. Now this shows a nonmodal window. To run the child window as a Modal Window, you need to open the control from the code behind.
Modifying the Code to Show the Child Window
Now from the LayoutRoot
, delete the ChildWindow
that we added just now before modifying the style. The UI inside the IDE will look as below:
Add a button inside the Layout root and name the control. Have a look into the below screenshot:
Now open the code behind file and add the click event handler for the Button
inside the constructor, just after the InitializeComponent()
call. Get the style of the custom child window from the page resource by specifying the key to it and store it in a member variable. Here is the code of it:
Inside the button click event implementation, create a ChildWindow
by specifying height, width, content to it. Also specify the style to it and call the Show()
method to open the Child Window.
Run you application and you will see the button in the screen. Click the "Show Message" button and you will see the Child Window popped up in the screen as shown below:
You can see that the background controls are wrapped with a semi transparent black layer. Thus your window becomes a modal window and you will not be able to click outside the window area.
So, the question here will be: Will we be able to change the color of the semi transparent layer? Yes, we can. I already mentioned it earlier in this article that the "Overlay
" border does the thing for you. Make sure that you are not changing any name of any control inside the template.
Open the XAML code and find the name "OverlayBrush
". You can find it here in the XAML code:
Change the value of the OverlayBrush
with a proper color code of your choice. Let us add a bluish color to it. Replace the value with "#7F000055
" as shown below:
Let us run it once again. Click the "Show Message" button to show the Child Window into the screen. Hey, you will notice that, this time the background color looks little bluish as per our requirement.
Demo Code
The complete XAML code is given below:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk=http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk
xmlns:d=http://schemas.microsoft.com/expression/blend/2008
xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006
mc:Ignorable="d"
x:Class="ChildWindowCustomizationDemo.MainPage"
Width="640" Height="480">
<UserControl.Resources>
<Style x:Key="ChildWindowStyle1" TargetType="sdk:ChildWindow">
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="TabNavigation" Value="Cycle"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="OverlayBrush" Value="#7F000055"/>
<Setter Property="OverlayOpacity" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:ChildWindow">
<Grid x:Name="Root">
<Grid.Resources>
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Background" Value="#FF1F3B53"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9"
Offset="0"/>
<GradientStop Color="#FF8399A9"
Offset="0.375"/>
<GradientStop Color="#FF718597"
Offset="0.375"/>
<GradientStop Color="#FF617584"
Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="grid" Background="#02FFFFFF"
HorizontalAlignment="Center" Height="14"
VerticalAlignment="Center" Width="15">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty=
"Visibility"
Storyboard.TargetName="X_Fuzz2">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty=
"Visibility"
Storyboard.TargetName="X_Fuzz1">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty=
"Visibility"
Storyboard.TargetName="X_Fuzz0">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Duration="0" To="0.95"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="X"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Duration="0"
To="0.85"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="X"/>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="
Visibility" Storyboard.TargetName=
"X_Fuzz2">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="
Visibility" Storyboard.TargetName=
"X_Fuzz1">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="
Visibility" Storyboard.TargetName=
"X_Fuzz0">
<DiscreteObjectKeyFrame KeyTime="0"
Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0"
To="0.5"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="X"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path x:Name="X_Fuzz2"
Data="F1 M 6.742676,3.852539
L 9.110840,1.559570 L 8.910645,
0.500000 L 6.838379,0.500000
L 4.902832,2.435547 L 2.967285,
0.500000 L 0.895020,0.500000
L 0.694824,1.559570 L 3.062988,
3.852539 L 0.527832,6.351563
L 0.689941,7.600586 L 2.967285,
7.600586 L 4.897949,5.575195
L 6.854004,7.600586 L 9.115723,
7.600586 L 9.277832,6.351563
L 6.742676,3.852539 Z"
Fill="#14C51900"
HorizontalAlignment="Center"
Height="8" Margin="0,-1,0,0"
Opacity="1"
RenderTransformOrigin="0.5,0.5"
Stretch="Fill"
Stroke="#14C51900"
Visibility="Collapsed"
VerticalAlignment="Center" Width="9">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1.3" ScaleX="1.3"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path x:Name="X_Fuzz1" Data="F1 M 6.742676,
3.852539 L 9.110840,1.559570
L 8.910645,0.500000 L 6.838379,
0.500000 L 4.902832,2.435547
L 2.967285,0.500000 L 0.895020,
0.500000 L 0.694824,1.559570
L 3.062988,3.852539 L 0.527832,
6.351563 L 0.689941,7.600586
L 2.967285,7.600586 L 4.897949,
5.575195 L 6.854004,7.600586
L 9.115723,7.600586 L 9.277832,
6.351563 L 6.742676,3.852539
Z" Fill="#1EC51900"
HorizontalAlignment="Center"
Height="8"
Margin="0,-1,0,0" Opacity="1"
RenderTransformOrigin="0.5,
0.5" Stretch="Fill"
Stroke="#1EC51900" Visibility="Collapsed"
VerticalAlignment="Center"
Width="9">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1.1" ScaleX="1.1"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path x:Name="X_Fuzz0" Data="F1 M 6.742676,
3.852539 L 9.110840,1.559570
L 8.910645,0.500000 L 6.838379,
0.500000 L 4.902832,2.435547
L 2.967285,0.500000 L 0.895020,
0.500000 L 0.694824,1.559570
L 3.062988,3.852539 L 0.527832,
6.351563 L 0.689941,7.600586
L 2.967285,7.600586 L 4.897949,
5.575195 L 6.854004,7.600586
L 9.115723,7.600586 L 9.277832,
6.351563 L 6.742676,3.852539 Z"
Fill="#FFC51900"
HorizontalAlignment="Center"
Height="8"
Margin="0,-1,0,0" Opacity="1"
Stretch="Fill" Stroke="#FFC51900"
Visibility="Collapsed" VerticalAlignment="
Center" Width="9"/>
<Path x:Name="X" Data="F1 M 6.742676,
3.852539 L 9.110840,1.559570
L 8.910645,0.500000 L 6.838379,
0.500000 L 4.902832,2.435547
L 2.967285,0.500000 L 0.895020,
0.500000 L 0.694824,1.559570
L 3.062988,3.852539 L 0.527832,
6.351563 L 0.689941,7.600586
L 2.967285,7.600586 L 4.897949,
5.575195 L 6.854004,7.600586
L 9.115723,7.600586 L 9.277832,
6.351563 L 6.742676,3.852539
Z" Fill="#FFFFFFFF"
HorizontalAlignment="Center"
Height="10"
Margin="0,-1,0,0" Opacity="0.7"
Stretch="Fill"
VerticalAlignment="Center"
Width="12">
<Path.Stroke>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#FF313131"
Offset="1"/>
<GradientStop Color="#FF8E9092"
Offset="0"/>
</LinearGradientBrush>
</Path.Stroke>
</Path>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<VisualState x:Name="Open">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="Overlay">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.3"
Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetProperty=
"(RenderTransform).(Children)
[0].ScaleX" Storyboard.TargetName="ContentRoot">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.25"
Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.4"
Value="1"/>
<SplineDoubleKeyFrame KeySpline="0,0,0.5,1"
KeyTime="00:00:00.45" Value="1.05"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.55"
Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetProperty=
"(RenderTransform).(Children)[0].ScaleY"
Storyboard.TargetName="ContentRoot">
<SplineDoubleKeyFrame
KeyTime="0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.25"
Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.4"
Value="1"/>
<SplineDoubleKeyFrame KeySpline="0,0,0.5,1"
KeyTime="00:00:00.45" Value="1.05"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.55"
Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Closed">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="Overlay">
<EasingDoubleKeyFrame
KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.3"
Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetProperty=
"(RenderTransform).(Children)[0].ScaleX"
Storyboard.TargetName="ContentRoot">
<SplineDoubleKeyFrame KeyTime="00:00:00.2"
Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.25"
Value="1.05"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.45"
Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetProperty=
"(RenderTransform).(Children)[0].ScaleY"
Storyboard.TargetName="ContentRoot">
<SplineDoubleKeyFrame KeyTime="00:00:00.2"
Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.25"
Value="1.05"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.45"
Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="Overlay" Background="{TemplateBinding OverlayBrush}"
HorizontalAlignment="Stretch" Margin="0" Opacity="
{TemplateBinding OverlayOpacity}" VerticalAlignment="Top"/>
<Grid x:Name="ContentRoot" HorizontalAlignment="
{TemplateBinding HorizontalAlignment}" Height="{TemplateBinding Height}"
RenderTransformOrigin="0.5,0.5" VerticalAlignment="
{TemplateBinding VerticalAlignment}" Width="{TemplateBinding Width}">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<Border BorderBrush="#14000000" BorderThickness="1"
Background="#14000000" CornerRadius="2"
HorizontalAlignment="Stretch" Margin="-1"
VerticalAlignment="Stretch"/>
<Border BorderBrush="#0F000000" BorderThickness="1"
Background="#0F000000" CornerRadius="2.25"
HorizontalAlignment="Stretch" Margin="-2"
VerticalAlignment="Stretch"/>
<Border BorderBrush="#0C000000" BorderThickness="1"
Background="#0C000000" CornerRadius="2.5"
HorizontalAlignment="Stretch" Margin="-3"
VerticalAlignment="Stretch"/>
<Border BorderBrush="#0A000000" BorderThickness="1"
Background="#0A000000" CornerRadius="2.75"
HorizontalAlignment="Stretch" Margin="-4"
VerticalAlignment="Stretch"/>
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="#FFFFFFFF" CornerRadius="2">
<Border CornerRadius="1.5" Margin="1">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#FF5F6A95" Offset="1"/>
<GradientStop Color="#FFC1F6FD" Offset="0"/>
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border x:Name="Chrome" BorderBrush="#FFFFFFFF"
BorderThickness="0,0,0,1" Width="Auto"
Height="25">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,0.528"
StartPoint="0.5,0">
<GradientStop Color="#FF0808A7"
Offset="1"/>
<GradientStop Color="Blue"
Offset="0"/>
<GradientStop Color="#FF5858E9"
Offset="0.478"/>
</LinearGradientBrush>
</Border.Background>
<Grid Height="Auto" Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<ContentControl Content="" FontWeight="Bold"
HorizontalAlignment="Stretch"
IsTabStop="False"
Margin="6,0,6,0" VerticalAlignment="Center"
Foreground="#FFCACACA"/>
<Button x:Name="CloseButton" Grid.Column="1"
HorizontalAlignment="Center" Height="14"
IsTabStop="False" Style=
"{StaticResource ButtonStyle}"
VerticalAlignment="Center" Width="15"
Cursor="Hand"/>
</Grid>
</Border>
<Border Background="{TemplateBinding Background}"
Margin="7" Grid.Row="1">
<ContentPresenter x:Name="ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding
VerticalContentAlignment}"/>
</Border>
</Grid>
</Border>
</Border>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Button x:Name="btnShowMessage" Content="Show Message"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</UserControl>
The complete C# code can be found here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace ChildWindowCustomizationDemo
{
public partial class MainPage : UserControl
{
Style childWindowStyle;
public MainPage()
{
InitializeComponent();
btnShowMessage.Click += (btnShowMessage_Click);
childWindowStyle = Resources["ChildWindowStyle1"] as Style;
}
private void btnShowMessage_Click
(object sender, System.Windows.RoutedEventArgs e)
{
ChildWindow messageBox = new ChildWindow
{
Width = 500.0,
Height = 200.0,
Content = "This is a custom Child Window in Silverlight.",
Style = childWindowStyle
};
messageBox.Show();
}
}
}
End Note
Hope that from this article, you got the basic concept of modifying the Child Window template. Next time when you need it, you will be able to change the same very easily. If you like this post, submit a feedback at the end of this post and let me know if you have any questions and/or suggestions. Also, don't forget to vote for this article.
I also tweet @kunal2383. Follow me there and share the link of this article to your friends and colleagues. Also, don't forget to follow my new site called Silverlight-Zone. You can find Silverlight and Windows Phone 7 related article news there. We also tweet all those articles in Twitter, Facebook and other services. If you want to include your articles, just drop a line to me in the discussion forum section placed on the top menu bar. Cheers!