Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / XAML

How to Implement Template Binding in Silverlight Custom Control?

5.00/5 (5 votes)
6 Apr 2011CPOL8 min read 36.2K  
How to implement template binding in Silverlight custom control

Introduction

Continuing to our second chapter of the series here on Silverlight Custom Control, in this chapter, we will discuss about dynamically setting the Content and other properties to our Custom Control that we implemented earlier. After reading this article, you will be able to create properties and set content dynamically to your control.

So, let's start describing them and learn something again today. These series of posts are mainly targeted for beginners but anyone can read them to refresh their learning. Don't forget to leave your comments at the end of the post. Any queries, please drop a line. I will try to help you as soon as I can. Don't forget to support me by providing your vote.

Background

I hope you read my previous posts. Those will help you to understand this one very easily. If you didn't read them or want to brush up before starting this chapter, find them here:

  1. How to create a Custom Control in Silverlight?
  2. How to design a Custom Control by editing the Part Template?

Once you are familiar with the previous context, let's start with this one. We will use the same example here which will give you more visualization on the sample code.

Working with the Template Part

Template parts are defined in the XAML inside the style. In our example, we have three parts called "PART_HeaderPanel", "PART_HeaderText" and "PART_Content". Those are already declared in the style and you can find them here:

image

Now it's time to initialize them in the code. You can escape this step but it is recommended that you should do this before working with those parts. In this article, we don't need them directly but we are doing this step here itself. We will talk more about this in the next chapter.

We will declare and initialize the template part by setting the TemplatePart attribute to the class. You need to do this for all the template parts. Again, this step is not mandatory but recommended. This also ensures that your user of this custom control should know what are the template parts that you used in your style. This information you will find in the meta class if you declare it here.

See the below sample code snippet to know how to declare the Template Part:

image

We are skipping the explanation and more code for the next chapter of the series.

Defining the Dependency Properties

As we discussed in our previous article, we will use dynamic content and brushes for our Custom Control. Here is the implementation of the same. In this section, we will create some properties to expose them to the user and set them dynamically on user request.

To do this, we must have to declare some dependency properties. Make sure that you are creating dependency properties only as they are used for Data Binding and Template Binding. If you use normal property, the code will not work and will throw an exception.

To implement the Dependency Property, open your control's class file (MyControl.cs, in our case) and inside the class, declare the same as per your requirement. To create a Dependency Property, you can use the code snippet called "propdp". This will create the same and help you to properly enter the definition.

For now, we will create two dependency properties to hold the Header text and Content for the main area. We will name them as "Caption" and "Content" respectively.

C#
#region Dependency Properties
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
        "Content", typeof(FrameworkElement), typeof(MyControl), new PropertyMetadata(null));
 
public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register(
        "Caption", typeof(string), typeof(MyControl), new PropertyMetadata(string.Empty));
#endregion
 
#region Properties
public FrameworkElement Content
{
    get { return (FrameworkElement)GetValue(ContentProperty); }
    set { SetValue(ContentProperty, value); }
}
 
public string Caption
{
    get { return (string)GetValue(CaptionProperty); }
    set { SetValue(CaptionProperty, value); }
}
#endregion

The above code will help you to understand the same. There, we created one property called "Caption" which is nothing but a string type. Setting the value here will change the Header text of our control. The other property called "Content" will be responsible to change the main content of our control.

Binding the Properties in the XAML

Once we created the dependency properties as per our requirement, it's time to bind them in the XAML. We have to modify our Template/Style present in our Generic.xaml page. Remember that you can't use normal Binding there, instead you have to use TemplateBinding. Have a look into the below screenshot:

image

You will notice that we added TemplateBinding to the properties respective to the parts. This will create the bonding between the control properties and dependency properties.

Setting Custom Value to the Properties

If we run the code now, voila!!! Our control doesn't have anything inside it. In our previous chapter, we had some text but nothing is here. Can you guess why this happened here? Just try to think the reason before scrolling next to read the answer.

image

If you check our dependency property, you will see that it has empty strings and null values as the default one that we binded. We didn't mention a new value from the user's side. So, you need to add the property values in your main page.

To do this, open the MainPage.xaml where we added our custom control. Try to add the Caption property to the control. You will notice that the property is present in the dropdown intellisense too. Hence, add a caption to the property.

image

For example, we will add "My Custom Control" as the header text / caption. You can add other text too. Here is the code snippet for your reference:

image

Now run it once again and this time you will see that the string which we entered to the caption property, has been added as header title.

image

Similarly, we will add the content control. As our content property type is FrameworkElement, hence we can't add normal string there. We have to add some framework elements. If you want to give a provision to your user to add anything like FrameworkElement and/or strings, use "string" as the type of the Dependency Property there.

In our case, we will add 2 textblocks inside a Stackpanel as the content of our custom control. Have a look into the below screenshot. The code snippet will give you better visibility of what we are doing here.

image

Once done, run your application. This time, you will view the content that we added right now. It is so easy, right? Yes...

image

Let us customize it further and create another Dependency Property to take the background color of the header panel; name it as HeaderPanelBackground. It will be a Brush type, so that, you can add any brush to it like Solid color or Gradient color.

Here is the full source code of our Custom control class:

C#
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
 
namespace CustomControlDemo
{
    [TemplatePart(Name = "PART_HeaderPanel", Type = typeof(Border))]
    [TemplatePart(Name = "PART_HeaderText", Type = typeof(TextBlock))]
    [TemplatePart(Name = "PART_Content", Type = typeof(ContentPresenter))]
    public class MyControl : Control
    {
        #region Dependency Properties
        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", 
                                         typeof(FrameworkElement), 
                                         typeof(MyControl), 
                                         new PropertyMetadata(null));
 
        public static readonly DependencyProperty CaptionProperty =
            DependencyProperty.Register("Caption",
                                         typeof(string),
                                         typeof(MyControl), 
                                         new PropertyMetadata(string.Empty));
 
        public static readonly DependencyProperty HeaderPanelBackgroundProperty =
            DependencyProperty.Register("HeaderPanelBackground",
                                         typeof(Brush),
                                         typeof(MyControl),
                                         new PropertyMetadata(new SolidColorBrush(
                                                                    Colors.Blue)));
        #endregion
 
        #region Public Properties
        public Brush HeaderPanelBackground
        {
            get { return (Brush)GetValue(HeaderPanelBackgroundProperty); }
            set { SetValue(HeaderPanelBackgroundProperty, value); }
        }
 
        public FrameworkElement Content
        {
            get { return (FrameworkElement)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }
 
        public string Caption
        {
            get { return (string)GetValue(CaptionProperty); }
            set { SetValue(CaptionProperty, value); }
        }
        #endregion
 
        public MyControl()
        {
            DefaultStyleKey = typeof(MyControl);
        }
    }
}

It's time to bind the template property to the style. Get the complete source code of the control template here:

XML
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomControlDemo">
    <Style TargetType="local:MyControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyControl">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="25"/>
                                <RowDefinition MinHeight="100" Height="*"/>
                            </Grid.RowDefinitions>
                            <Border x:Name="PART_HeaderPanel" 
                                    Background="{TemplateBinding HeaderPanelBackground}" 
                                    Grid.Row="0">
                                <TextBlock x:Name="PART_HeaderText" 
                                            Text="{TemplateBinding Caption}" 
                                            Foreground="White" 
                                            VerticalAlignment="Center"/>
                            </Border>
                            <ContentPresenter x:Name="PART_Content" 
                                              Grid.Row="1"
                                              Content="{TemplateBinding Content}"/>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Similarly, add the HeaderPanelBackground property value to the MainPage where you added the Custom Control. For example, we will use Green color while demonstrating now.

Get the full code from here (just for reference):

XML
<UserControl x:Class="CustomControlDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:CustomControlDemo="clr-namespace:CustomControlDemo" mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
 
    <Grid x:Name="LayoutRoot" Background="White">
        <CustomControlDemo:MyControl 
            Width="200"
            Height="200"
            HeaderPanelBackground="Green"
            Background="Yellow"
            BorderBrush="Red"
            BorderThickness="1"
            Caption="My Custom Control">
            <CustomControlDemo:MyControl.Content>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="First line in Content"/>
                    <TextBlock Text="Second line in Content"/>
                </StackPanel>
            </CustomControlDemo:MyControl.Content>
        </CustomControlDemo:MyControl>
    </Grid>
</UserControl>

Run the application now, once again. Oh yeah, you will see that the header now has a Green background. Change it to something else, it will automatically change. You can further customize it to dynamically change it by user input.

image

Hope this thing now cleared the implementation part and their usage. Try something more and you will get a chance to explore it more.

Setting Default Value to the Template

Sometimes, you may want to set the default value to the template directly. User can use the same color or can change it from the place where they use it. To do this, you can use the Setter tag to insert default property value to the style. If you start typing the property name, it will automatically come in the intellisense.

image

Set the values properly for the respective properties. Find the code snippet here:

image

If you run the application now, you will not see any change. To see the default value effect, go to the MainPage and remove the properties that we already added to the control (as shown below).

image

Once you removed the properties, run the solution. You will see those default values as part of your UI now.

image

Is it clear now? Hope, this cleared the smoke from your eyes. Once you read the complete post and follow those steps properly, you will be able to create custom controls in Silverlight very easily.

What Next?

Nothing much. This series will help you to understand the implementation of Custom Controls. Though it is demonstrated in Silverlight, it will be the same for WPF, Windows Phone 7 too. In the next chapter, we will discuss the Control parts from code behind (i.e., inside the control class). I will publish that part soon. That will be the last chapter of the series and it will cover more on the Custom control part.

Follow my blog for articles and news. Also find me on Twitter @kunal2383. You will get update there too. Also, I have a blog called Silverlight-Zone, where I post latest articles on Silverlight, LightSwitch, XAML, Blend, XNA and related articles by digging the internet. We update the site very frequently. You may follow us on twitter @SilverlightZone.

Thank you so much for reading my articles/tutorials. I appreciate your feedback and/or suggestions. Happy coding!

I appreciate your vote and support.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)