As a Silverlight control developer, you may encounter a need to create a custom content control. This type of control allows the consumers to place anything they want in certain areas of your control. In Silverlight, you may have noticed that the Button control has a content property. You can essentially put anything you want in a button. I’m going to show you how you can create a control to do this.
We are going to create a control that has a header and body. The final result will look like the image below:
[img]http://dl.iteye.com/upload/attachment/204796/b2ff7de3-f4f3-3d3e-8d9f-83e0167bf4ea.jpeg[/img]
Step 1 – Setup the Solution
The first step in creating our control is to ensure that our Visual Studio environment is setup correctly. We’ll have our basic Silverlight Application project and Web Project to test it in. However, we are going to add a Silverlight Class Library project and add a reference to it in our Silverlight Application project.
The next step is what gets a lot of developers. Add a “themes” folder in our controls project (Silverlight Class Library project). Inside the “themes” folder, add a new text file and name it “generic.xaml”. Make sure that the folder/file names are lower case!
[img]http://dl.iteye.com/upload/attachment/204798/785affdd-5eac-3c03-90e6-ab48260cb025.jpeg[/img]
Silverlight 2 does not support themes like WPF does. However, inserting the “themes/generic.xaml” file inside our controls project does yield us the ability to define our CustomContentControl style/template.
Step 2 – Create the Custom Content Control
Now that our solution is ready, let’s add our CustomContentControl to our controls project. We’ll be inheriting from the ContentControl object. Therefore by default, we’ll already have a Content property. However we want to create an additional Header property so that other developers can put whatever they want in the header. Here’s our CustomContentControl code:
Here we have our control which inherits from ContentControl and has a Header property defined. There’s one last thing to mention about our control. Check out line 17. We set the DefaultStyleKey to a resource object which we are going to define in our generic.xaml file. So let’s do that.
Step 3 – Create Control’s DefaultStyleKey (generic.xaml)
In step 2 we saw that after our CustomContentControl was instantiated we immediately wired up its DefaultStyleKey. In the generic.xaml file we’ll define our style/template for our CustomContentControl. The style will automatically be found and used for our control. Here’s the style for our control:
At a quick glance take note that we have a ContentControl for both the Header and Content properties of our CustomContentControl. When the template is bound, the Header and Content values will be placed inside our ContentControls defined here.
Step 4 – Use the CustomContentControl
Now that we have the solution setup, our control coded, and our default style/template defined in the generic.xaml file, we can use our control. Here’s the page XAML that uses the control.
If you wish to add events to your custom content control, I've written another post which can be found [url=http://www.mostlydevelopers.com/blog/post/2009/07/06/Silverlight-Custom-Content-Control-with-Events.aspx]here[/url].
We are going to create a control that has a header and body. The final result will look like the image below:
[img]http://dl.iteye.com/upload/attachment/204796/b2ff7de3-f4f3-3d3e-8d9f-83e0167bf4ea.jpeg[/img]
Step 1 – Setup the Solution
The first step in creating our control is to ensure that our Visual Studio environment is setup correctly. We’ll have our basic Silverlight Application project and Web Project to test it in. However, we are going to add a Silverlight Class Library project and add a reference to it in our Silverlight Application project.
The next step is what gets a lot of developers. Add a “themes” folder in our controls project (Silverlight Class Library project). Inside the “themes” folder, add a new text file and name it “generic.xaml”. Make sure that the folder/file names are lower case!
[img]http://dl.iteye.com/upload/attachment/204798/785affdd-5eac-3c03-90e6-ab48260cb025.jpeg[/img]
Silverlight 2 does not support themes like WPF does. However, inserting the “themes/generic.xaml” file inside our controls project does yield us the ability to define our CustomContentControl style/template.
Step 2 – Create the Custom Content Control
Now that our solution is ready, let’s add our CustomContentControl to our controls project. We’ll be inheriting from the ContentControl object. Therefore by default, we’ll already have a Content property. However we want to create an additional Header property so that other developers can put whatever they want in the header. Here’s our CustomContentControl code:
Public Class CustomContentControl
Inherits ContentControl
Public Shared ReadOnly HeaderProperty As DependencyProperty = DependencyProperty.Register("Header", GetType(UIElement), GetType(CustomContentControl), Nothing)
Public Property Header() As UIElement
Get
Return DirectCast(Me.GetValue(CustomContentControl.HeaderProperty), UIElement)
End Get
Set(ByVal value As UIElement)
Me.SetValue(CustomContentControl.HeaderProperty, value)
End Set
End Property
Public Sub New()
MyBase.New()
Me.DefaultStyleKey = GetType(CustomContentControl)
End Sub
End Class
Here we have our control which inherits from ContentControl and has a Header property defined. There’s one last thing to mention about our control. Check out line 17. We set the DefaultStyleKey to a resource object which we are going to define in our generic.xaml file. So let’s do that.
Step 3 – Create Control’s DefaultStyleKey (generic.xaml)
In step 2 we saw that after our CustomContentControl was instantiated we immediately wired up its DefaultStyleKey. In the generic.xaml file we’ll define our style/template for our CustomContentControl. The style will automatically be found and used for our control. Here’s the style for our control:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentControlExample.Controls">
<!-- CustomContentControl -->
<Style TargetType="local:CustomContentControl">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomContentControl">
<Border Background="White" BorderBrush="#87AFDA" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Column="0" Grid.Row="0" Background="#D4E6FC" BorderThickness="0,0,0,1" BorderBrush="#87AFDA">
<ContentControl Content="{TemplateBinding Header}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Foreground="#224499" FontWeight="Bold" FontFamily="Arial" FontSize="12" Margin="3,3,3,3" />
</Border>
<ContentControl Grid.Column="0" Grid.Row="1" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" FontFamily="Arial" FontSize="{TemplateBinding FontSize}" FontStretch="{TemplateBinding FontStretch}" Foreground="{TemplateBinding Foreground}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
At a quick glance take note that we have a ContentControl for both the Header and Content properties of our CustomContentControl. When the template is bound, the Header and Content values will be placed inside our ContentControls defined here.
Step 4 – Use the CustomContentControl
Now that we have the solution setup, our control coded, and our default style/template defined in the generic.xaml file, we can use our control. Here’s the page XAML that uses the control.
<UserControl x:Class="ContentControlExample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ex="clr-namespace:ContentControlExample.Controls;assembly=ContentControlExample.Controls"
Width="300" Height="200">
<Grid x:Name="LayoutRoot" Background="White">
<ex:CustomContentControl x:Name="myCustomContentControl">
<ex:CustomContentControl.Header>
<TextBlock Text="This is the Header" />
</ex:CustomContentControl.Header>
<ex:CustomContentControl.Content>
<StackPanel Orientation="Vertical" Margin="5">
<TextBlock Text="This is the body or content." Margin="0,0,0,5" />
<Button Content="Click Me!" Width="100" Height="30" />
</StackPanel>
</ex:CustomContentControl.Content>
</ex:CustomContentControl>
</Grid>
</UserControl>
If you wish to add events to your custom content control, I've written another post which can be found [url=http://www.mostlydevelopers.com/blog/post/2009/07/06/Silverlight-Custom-Content-Control-with-Events.aspx]here[/url].