Dot Net For All

Working with WPF Templates

WPF Templates

What is a template in laymen’s term? A template is a shape or mold which we can apply on a  look less or some randomly shaped piece of some object. E.g. suppose we have some randomly shaped clay and we want that clay to attain some shape may be like circle or triangle. This we can achieve by having a pre molded iron shape and pressing hard on that clay by keeping the other properties of clay intact such as hardness. WPF templates help us to achieve the same functionality. The controls in WPF are basically look less or they have some pre-defined shape which we may want to change in some scenario.

There are two ways in which we can alter the look and feel of a control in WPF Templates and they are

  1. ControlTemplate
  2. DataTemplate

I will discuss here all of them one by one.

  1. ControlTemplate –

    Control template is used to alter the UI of a control provided by the WPF.
    All the controls in WPF are derived from the Control class which contains a property named Template which is of type ControlTemplate which is used to change the appearance of the control.Please check the code sample shown below in which we have two buttons. The first one is the default button and the second button’s template is changed to have user defined appearance

    <Button Click="Button_Click" Content="Click Me" Width="200" Height="50" ></Button>
            <Button Click="Button_Click" Content="Click Me" Margin="5">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Grid Width="200" Height="50">                      
                            <Ellipse Stroke="Black" Fill="LightBlue">                          
                            </Ellipse>                                            
                        </Grid>
                    </ControlTemplate>
                </Button.Template>
      </Button>
    

    And the UI of the above code will be displayed as shown below.

    ControlTemplate in WPF

    The above UI has one problem, the second button does not show the Content of the button as the default style of the control is replaced by the new controltemplate. This problem can be resolved by using the ContentPresenter of the control which is a placeholder for the content of the control. Please have a look at the code below

    <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Grid Width="200" Height="50">                      
                            <Ellipse Stroke="Black" Fill="LightBlue">                          
                            </Ellipse>
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>                       
                        </Grid>
                    </ControlTemplate>
                </Button.Template>
    

    As the Grid is an overlay panel in which the controls arrange themselves one above other if the row and columns are not provided for them that is why the contentpresenter is placed easily on Ellipse. After above change the controls will look as shown below.

  2. DataTemplate –

    Datatemplate is used to give a UI to the data of a control or we can say to represent data in UI we need to define a data template for the particular type. The example of the datatemplate we will see in the below code.Suppose I have an ItemsControl in the WPF window as shown below. This is one of the WPF templates which is bit confusing.

        <StackPanel>       
            <ItemsControl ItemsSource="{Binding PersonList}"></ItemsControl>          
         </StackPanel>
    

    And the code behind for binding part is as shown below.

    public partial class MainWindow : Window
        {
            public MainWindow()
            {
                PersonList = new List<Person>() { new Person() { Age=31, Name = "Vikram Chaudhary" },
                new Person() { Age= 30, Name = "Another Person" }};
                this.DataContext = this;
                InitializeComponent();
               
            }
    
            public IList<Person> PersonList { get; set; }
        }
    
        public class Person
        {
            public int Age { get; set; }
            public string Name { get; set; }
        }
    

    As we can see from the above code our list is being bound to the list of person but since we do not have any UI for the items of the ItemsControl, that is why the items render themselves with the object.ToString() form of the data as shown below.

    Now the data in the ItemsControl does not have any visualization and if we want to have some UI representation of the data we can define a DataTemplate as shown below.

      <Window.Resources>
            <DataTemplate DataType="{x:Type local:Person}">
                <Border BorderThickness="2" BorderBrush="Red" Margin="2">
                    <StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Name: "></TextBlock>
                            <TextBlock Text="{Binding Name}"></TextBlock>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Age: "></TextBlock>
                            <TextBlock Text="{Binding Age}"></TextBlock>
                        </StackPanel>
                    </StackPanel>
                </Border>
            </DataTemplate>
        </Window.Resources>
    

     

    And after the above template is applied the UI we will get is as shown below,

    This is due to the reason that whenever WPF renders a UI and it finds that there is some class is being rendered, it starts looking up the visual tree to check for any datatemplate present for that particular object type. If it finds the datatemplate for the object it renders that datatemplate otherwise it will renders the object.ToSting() form of that object.
    There is one more way by which we can set the datatemplate of ItemsControl. This can be done by setting the ItemTemplate property of the ItemsControl as shown below

    <ItemsControl ItemsSource="{Binding PersonList}" ItemTemplate="{StaticResource PersonTemplate}"></ItemsControl>

    And having a datatemplate in the resources as shown below

    <DataTemplate x:Key="PersonTemplate">
                <Border BorderThickness="2" BorderBrush="Red" Margin="2">
                    <StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Name: "></TextBlock>
                            <TextBlock Text="{Binding Name}"></TextBlock>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Age: "></TextBlock>
                            <TextBlock Text="{Binding Age}"></TextBlock>
                        </StackPanel>
                    </StackPanel>
                </Border>
            </DataTemplate>
    

In this article I have discussed two types of WPF templates i.e. ControlTemplate and Datatemplate and their usages. I hope you have been able to understand and differentiate among these two after this article.

Please let me know your thoughts about the article.

Like my facebook page at Dot Net For All

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview