Dynamically Adding or Retrieves Templates Into Controls in WPF Using C#

Introduction

Sometimes we need to add templates dynamically into controls in WPF. Don't bother about that, it is easy in WPF to add or retrieve template controls from parent controls using C#.

To add templates dynamically, simply use a Framework Element Factory, Data Template or Control Template class and to retrieve controls dynamically use the Content Presenter, Data Template or Control Template class.

Let's discuss each of those classes.

  1. FrameworkElementFactory
  2. FrameworkElement
  3. DataTemplate
  4. ControlTemplate

FrameworkElementFactory: This class creates templates dynamically. It is the subclass of the Framework Template such as ControlTemplate or Data Template. This class has one parameterized constructor that takes a control type as a parameter, it also has a property named Type that gets or sets the type of template to be added. The function "setBinding()" of Framework Element Factory class helps to bind data with an element and the "setValue" function helps to set the property value of the element.

ContentPresenter: You typically use the Content Presenter in the Control Template of a Content Control to specify where the content is to be added. Every Content Control type has a Content Presenter in its default Control Template.

When a Content Presenter object is in a Control Template of a ContentControl, the Content, Content Template and Content Template Selector properties get their values from the properties of the same names of the ContentControl. You can have the Content Presenter property to get the values of these properties from other properties of the templated parent by setting the Content Source property or binding to them.

DataTemplate: Data Templates are similar in concept to Control Templates. They give you a very flexible and powerful solution to replace the visual appearance of a data item in a control, like List Box, Combo Box or List View. In my opinion this is one of the key success factories of WPF. If you don't specify a data template then WPF takes the default template that is just a Text Block. If you bind complex objects to the control then it just calls ToString() on it. Within a DataTemplate, the Data Context is set to the data object. So you can easily bind against the data context to display various members of your data object. The Visual Tree property helps get or set a Framework Element Factory.

ControlTemplate: The Control Template allows you to specify the visual structure of a control. The control author can define the default Control Template and the application author can override the Control Template to reconstruct the visual structure of the control.

Control templating is one of the many features offered by the WPF styling and templating model. The styling and templating model provides you with such great flexibility that in many cases you do not need to write your own controls. If you are an application author that wants to change the visualization of your control or to replace the Control Template of an existing control then see the Styling and Templating topic for examples and an in-depth discussion.

Let's take an example to add a template to a ListBox item. Here I will explain how to add a Check Box as a template into the items of a ListBox. I will set the CheckBox properties, such as Name, Width and Click Event and bind the Check Box to data.

Create the object of the Framework Element Factory class and pass the CheckBox type as a parameter. Call the SetValue function two times to set the Name and Width Property of the CheckBox. The SetValue method takes two parameters, DependencyProperty and Object. See the following code:

FrameworkElementFactory FEF = new FrameworkElementFactory (typeof(CheckBox));
FEF.SetValue(
CheckBox.NameProperty"txtChecked");
FEF.SetValue(
CheckBox.WidthProperty, 50.00);

To add the click event of the CheckBox call the AddHandler method of the FrameworkElementFactory class. This method adds an event handler for the routed event to the instances created by this factory.

This member is overloaded. For complete information about this member, including syntax, usage, and examples, click a name in the overload list.

FEF.AddHandler(CheckBox.ClickEventnewRoutedEventHandler(CheckBox_CheckChanged), true);

Call the setBinding method of the FrameworkElementFactory class to set the binding of the content and the isChecked property of CheckBox. The setBinding method takes two parameters, DependencyProperty and the object of the Binding class. In the following code I have initialized the binding class and passed the name of the property of checkbox as a string to the constructor with whom the data is to be banded. Again I

Binding CBG = new Binding(this.ContentPath);
FEF.SetBinding(CheckBox.ContentProperty, CBG);          
Binding SBG = new Binding();
SBG.Path = 
new PropertyPath(this.IsSelectPath);
FEF.SetBinding(CheckBox.IsCheckedProperty, SBG);

Create the object of DataTemplet or CorntrolTemplate class as per requirements and set the VisualTree property to the Framework Element Factory Class. Here I have created an object of the DataTemplate class and set the VisualTree to the object of FrameworkElement Class:

DataTemplate IT = new DataTemplate();
IT.VisualTree = FEF;

Finally set the template of the control whose template wants to be set to the object of the DataTemplate or ControlTemplate.

this.ItemTemplate = IT;

Now let's discuss retrieval of the templates. To retrieve a template control as I mentioned above there is a need of a ContentPrasanter, DataTemplate or ControlTemplate class. Though we have taken an example of a ListBox and CheckBox as the template container and template, we will discuss how to retrieve an object of a CheckBox from the ItemTemplate of a ListBox.

Here we will retrieve a template from SelectItem of a ListBox. Create the object of ListBoxItem and by typecasting set the ListBoxItem object equal to SelectItem of ListBox.

ListBoxItem LBI = (ListBoxItem)this.SelectedItem;

Use VisualTreeHelper's GetChild function to chield template:

ContentPresenter CP = (ContentPresenter)VisualTreeHelper.GetChild(LBI, ind);

Create the object of DataTemplate and by typecasting set it equal to an object of the content presenter.

DataTemplate DT = CP.ContentTemplate;

Finally call the FindName method of DataTemplate and set it to a CheckBox object. The FindName method takes two parameters, the name of a template control and a container object of. See the code below:

CheckBox target = (CheckBox) DT.FindName("txtChecked ", CP);

If you have any query then please feel free to comment or if this article solves your problem then don't forget to like it.