Different Types of Templates in WPF
Templates provides the visual and data repression of WPF element, by using Templates we can easily change the visual Look and feel of WPF elements and data presentation. In WPF each control has default template associated with it which give the control's default appearance. WPF provides three types of Templates to update the Look and Feel of elements
Control Template
Data Template
ItemPanel Template
WPF elements have Template, ContentTemplate and ItemTemplate Properties, while DataTemplate and ControlTemplate are the types. Template property defines the Visual Representation of control and ContentTemplate and ItemTemplate properties define the Data part representation of control. Template Property accepts the ControlTemplate object while ContentTemplate and ItemTemplate accept the object of DataTemplate.
Control Template
The Control Template is responsible for visual appearance and behaviours of WPF UI Controls. By changing the control template we can change the default look and feel of control. There is a Dependency Property "Template" in each control. We can define control template for a control.
- In Resource using Control Template with key
- In Style
- Inline Template
Example
Suppose we want to make a round red button
In Resource using Control Template with key
We can define ControlTemplete inside resource
<Window.Resources>
<ControlTemplate x:Key="redRoundButton" TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Window.Resources>
Full XAML code
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Window.Resources>
<ControlTemplate x:Key="redRoundButton" TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Window.Resources>
<Grid>
<Button Template="{StaticResource redRoundButton}" Content="Control Template"></Button>
</Grid>
</Window>
As we can see by changing the Control Template we can customize the button appearance.
Now we can see the Content("ControlTemplate") inside the button is missing. When we change the control template for showing the content we need to use ContentPresenter, you can read about this topic in following post "WPF ContentPresenter"
See below code with "ContentPresenter"
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Window.Resources>
<ControlTemplate x:Key="redRoundButton" TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Window.Resources>
<Grid>
<Button Template="{StaticResource redRoundButton}" Content="Control Template"></Button>
</Grid>
</Window>
In Style
We can define ControlTemplete inside sytle
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Window.Resources>
<Style x:Key="redRoundButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Button Style="{StaticResource redRoundButtonStyle}" Content="Control Template"></Button>
</Grid>
</Window>
Inline Template
We can define inline tempate. there is the "Template" Property inside which "ControlTemplate" can be define.
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Grid>
<Button Content="Control Template" Foreground="Wheat">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>
Inline Template With Styles
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Grid>
<Button Content="Control Template">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Grid>
</Window>
Change Control template using Trigger
Control Template can be change with trigger.See below example
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Grid>
<Button Content="demo" Width="50" Height="50" >
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="50" Height="50">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Window>
Button will change in red round button as mouse hover on it.
Trigger to change the color of Round button from Red to Light Blue on mouse hover
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Grid>
<Button Content="Control Template" Width="100" Height="100" >
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100" Name="redInnerCircle">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="redInnerCircle" Property="Fill" Value="lightblue"></Setter>
<Setter TargetName="redInnerCircle" Property="Cursor" Value="Hand"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>
Without hover
On Mouse Hover
A Control inside another control using control template
Problem :Required Textbox control inside the button and content of button to show in inside textbox. See the below code how to acheive this
<Window x:Class="GurukulTree.ControlTemplateDemo"
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"
mc:Ignorable="d"
Title="ControlTemplateDemo" Height="200" Width="300">
<Grid>
<Button Content="Control Template" Name="btn" >
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="100" Height="100" Name="radCircle">
<Ellipse.Fill>
<SolidColorBrush Color="Red"></SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<TextBox Width="92" Height="30" Text="{Binding ElementName=btn, Path=Content}"></TextBox>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="radCircle" Property="Cursor" Value="Hand"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>
Data Template
As control template work for aperance of conrol, DataTemplate gives the ability to change the the appearance data. it gives the flexibility to change the representation of data for Collection of data, it is mostly used with Item Controls such as List Box, Combo box, List view, Data Grid even we can use those control which has ContentTemplate as button, ContentControlIn Wpf most of the control have two way to represent the data
- ContentTemplate
- ItemTemplate
- Template Property denotes the apperance of a Control
- While ContentTemplate denotes the apperance of content part of a control
- While ItemTemplate denotes the apperance for content part of collection controls
- So Template property of the control accepts the object of ControlTemplate while ContentTemplate property and ItemTemplate property accept the object of DataTemplate.
DataTemplate with ContentTemplate
DataTemplate with ItemTemplate
Data Template : ContentTemplate
ContentTemplate type accept the DataTemplate to display the content of the ContentControl.
<Window.Resources>
<DataTemplate x:Key="datatemplate">
<TextBlock Text="{Binding}" FontSize="11" FontWeight="Bold" TextWrapping="Wrap"></TextBlock>
</DataTemplate>
</Window.Resources>
<ContentControl Name="contentControl" ContentTemplate="{StaticResource datatemplate}"
Content="DataTemplate Demo with Content Template"/>
Complete Example
<Window x:Class="GurukulTree.DataTemplateDemo"
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"
mc:Ignorable="d"
Title="DataTemplateDemo" Height="200" Width="300">
<Window.Resources>
<DataTemplate x:Key="datatemplate">
<TextBlock Text="{Binding}" FontSize="11" FontWeight="Bold" TextWrapping="Wrap"></TextBlock>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Name="contentControl" ContentTemplate="{StaticResource datatemplate}"
Content="DataTemplate Demo with Content Template"/>
</Grid>
</Window>
Now, we try to achieve the below example with the DataTemplae.
<Window x:Class="GurukulTree.DataTemplateDemo"
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"
mc:Ignorable="d"
Title="DataTemplateDemo" Height="200" Width="300">
<Window.Resources>
<DataTemplate x:Key="datatemplate">
<TextBlock Text="{Binding}" FontSize="11" FontWeight="Bold" TextWrapping="Wrap" Background="Yellow"></TextBlock>
</DataTemplate>
</Window.Resources>
<Grid>
<Button Name="contentControl" ContentTemplate="{StaticResource datatemplate}" Width="150" Height="100"
Content="DataTemplate Demo with ContentTemplate"/>
</Grid>
</Window>
Data Template : ItemTemplate
ItemTemplate property accept the DataTemplate to display the content of the ItemControls. now we want to acheive below representaion of List ItemControl.
using System.Collections.Generic;
using System.Windows;
namespace GurukulTree
{
public partial class DataTemplateDemo : Window
{
public DataTemplateDemo()
{
InitializeComponent();
CustomeLst = new List<Customer>();
CustomeLst.Add(new Customer()
{
Propname = "Name",
Propvalue = "John",
});
CustomeLst.Add(new Customer()
{
Propname = "Age",
Propvalue = "23",
});
CustomeLst.Add(new Customer()
{
Propname = "Weight",
Propvalue = "60",
});
this.DataContext = this;
}
private List<Customer> customeLst;
public List<Customer> CustomeLst
{
get
{
return customeLst;
}
set
{
customeLst = value;
}
}
}
public class Customer
{
private string propname;
private string propvalue;
public string Propname
{
get
{
return propname;
}
set
{
propname = value;
}
}
public string Propvalue
{
get
{
return propvalue;
}
set
{
propvalue = value;
}
}
}
}
<Window x:Class="GurukulTree.DataTemplateDemo"
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"
mc:Ignorable="d"
Title="DataTemplateDemo" Height="200" Width="300">
<Grid>
<ListBox ItemsSource="{Binding CustomeLst}" BorderBrush="Transparent"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5,15,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Propname}" FontWeight="Bold" Foreground="Red" Width="50" />
<TextBox Grid.Column="1" Text="{Binding Propvalue}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Right now Reader has to do analysis for ItemPanel Template we will very come with ItemPanel Template