Creating a ContentControl in Silverlight

Recently I happed to work a lot in Silverlight and also needed to create new Controls. While a UserControl is useful to separate the pieces of an application, I needed that separation with the capability to inject other controls as well. Therefore Silverlight has a class called ContentControl. I derived from it and am now able to use this control as a decorator for the stuff that I can pass in. Because I did all this experimental work at home today on this Friday (actually it already is Saturday), I want me to remember all this when I go back to work on Monday. Coincidently, I did not write a blog post for quite some time, so I decided to to both at the same time: here is me writing shortly about how to create custom ContentControls in Silverlight.

I created a normal Silverlight 3 Application in VS2010 Beta2 and added a new item, a user control. Then I changed the UserControl to a ContentControl by editing the xaml file like below.

<ContentControl x:Class="SilverlightApplication2.CCC1"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SilverlightApplication2">
    <ContentControl.Style>
        <Style TargetType="local:CCC1">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:CCC1">
                        <StackPanel Background="{TemplateBinding Background}">
                            <TextBlock x:Name="text1" Text="Hallo…."></TextBlock>
                            <ContentPresenter x:Name="conEl"/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ContentControl.Style>
</ContentControl>

Notice that I declared the structure of the control in a ControlTemplate directly inside the content control. You could totally have this style in a resource dictionary, but i really like having everything where it is needed. Like this I can only have one of these content controls on a page. I named the TextBlock and the ContentPresenter because I want to access them in the code behind. There I have fields for them which I assign values when a template is applied to the control. I do this by overriding the OnApplyTemplate method.

using System;
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 SilverlightApplication2
{
    public partial class CCC1 : ContentControl
    {
        private TextBlock textBlock;
        private UIElement ContentElement
        {
            get { return this.Content as UIElement; }
        }

        public CCC1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(CCC1_Loaded);
        }

        private void CCC1_Loaded(object sender, RoutedEventArgs e)
        {
            Console.WriteLine(this.ContentElement.GetValue(UserControl.WidthProperty));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.textBlock = base.GetTemplateChild("text1") as TextBlock;
        }
    }
}

I put a breakpoint at the writeline to get notified when the control is loaded in order to be able to see what the content actually is. That pretty much is the custom ContentControl. I use it in the MainPage.xaml like below.

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006
    xmlns:local="clr-namespace:SilverlightApplication2">

    <Grid x:Name="LayoutRoot" Background="Violet">
        <local:CCC1 Width="200" Height="150">
            <Canvas Width="350" Height="200" Background="Yellow">
                <Button Content="Hallo"></Button>
            </Canvas>
        </local:CCC1>
    </Grid>
</UserControl>

Notice that I made the custom content control (CCC1) 200 pixels wide and 150 pixels high. Its content I deliberately set to a bigger size to demonstrate that the custom content control is not streched. It would have streched if it was just a UserControl with the canvas placed in it.

Looks nice, doesn’t it?

customcontentcontrol

That’s it for this blog post. If you do not already, please follow me on twitter at www.twitter.com/halllo.

Manuel

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s