Tuesday, June 27, 2017

Different Types of Templates in WPF

Template provide the visual of WPF element, by using WPF we can change the visual Look and feel of WPF elements
WPF provides three types of Templates to update the Look and Feel of elements

  • Control Template
  • Data Template
  • ItemPanel Template
Control Template

The Control Template is responsible for visual appearance and behaviors of wpf UI Controls, by changing the control template we can change the default look and feel of a controls.
There is a Dependency Property of Template in each control, style or we can directly define in control template.
Example
Suppose we want to make a round red button

1) In Resource using Control Template with key

We can define ControlTemplete inside resource
    <Window.Resources>
        <ControlTemplate x:Key="gradientRoundButton">
            <Grid>
                <Ellipse Width="100" Height="100">
                    <Ellipse.Fill>
                        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                            <GradientStop Color="Blue" Offset="0" />
                            <GradientStop Color="Green" Offset="0.5" />
                            <GradientStop Color="Red" Offset="1.0" />
                        </LinearGradientBrush>
                    </Ellipse.Fill>
                </Ellipse>
            </Grid>
        </ControlTemplate>
    </Window.Resources>

Full Code
<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="gradientRoundButton">
            <Grid>
                <Ellipse Width="100" Height="100">
                    <Ellipse.Fill>
                        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                            <GradientStop Color="Blue" Offset="0" />
                            <GradientStop Color="Green" Offset="0.5" />
                            <GradientStop Color="Red" Offset="1.0" />
                        </LinearGradientBrush>
                    </Ellipse.Fill>
                </Ellipse>
            </Grid>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Button Template="{StaticResource gradientRoundButton}" Content="Control Template"></Button>
    </Grid>
</Window>

As we can see by change the Control Template we can customize the button appearance.
Now we can see the Content inside the button is missing
For showing the content we need to use ContentPresenter, you can read about this topic in following post “WPF ContentPresenter”

<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="gradientRoundButton" TargetType="Button">
            <Grid>
                <Ellipse Width="100" Height="100">
                    <Ellipse.Fill>
                        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                            <GradientStop Color="Blue" Offset="0" />
                            <GradientStop Color="Green" Offset="0.5" />
                            <GradientStop Color="Red" Offset="1.0" />
                        </LinearGradientBrush>
                    </Ellipse.Fill>
                </Ellipse>
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Grid>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Button Template="{StaticResource gradientRoundButton}" Content="Control Template"></Button>
    </Grid>
</Window>

2) In Style

<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Window.Resources>
        <Style x:Key="gradientRoundButtonStyle" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid>
                            <Ellipse Width="100" Height="100">
                                <Ellipse.Fill>
                                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                                        <GradientStop Color="Blue" Offset="0" />
                                        <GradientStop Color="Green" Offset="0.5" />
                                        <GradientStop Color="Red" Offset="1.0" />
                                    </LinearGradientBrush>
                                </Ellipse.Fill>
                            </Ellipse>
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Button Style="{StaticResource gradientRoundButtonStyle}" Content="Control Template"></Button>
    </Grid>
</Window>



3) Inline Template
Suppose we are looking for a button like below


<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Grid>
        <Button Content="Control Template" Foreground="Wheat">
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <Ellipse Width="120" Height="120" Fill="Gray" />
                        <Ellipse Width="100" Height="100">
                            <Ellipse.Fill>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                                    <GradientStop Color="Blue" Offset="0" />
                                    <GradientStop Color="Green" Offset="0.5" />
                                    <GradientStop Color="Red" Offset="1.0" />
                                </LinearGradientBrush>
                            </Ellipse.Fill>
                        </Ellipse>
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Grid>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </Grid>
</Window>


4) Inline Template With Styles


<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Grid>
        <Button Content="Control Template" Foreground="Wheat">
            <Button.Style>
                <Style TargetType="Button">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="Button">
                                <Grid>
                                    <Ellipse Width="120" Height="120" Fill="Gray" />
                                    <Ellipse Width="100" Height="100">
                                        <Ellipse.Fill>
                                            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                                                <GradientStop Color="Blue" Offset="0" />
                                                <GradientStop Color="Green" Offset="0.5" />
                                                <GradientStop Color="Red" Offset="1.0" />
                                            </LinearGradientBrush>
                                        </Ellipse.Fill>
                                    </Ellipse>
                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Button.Style>
        </Button>
    </Grid>
</Window>


5) Using Trigger With Control Template

<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Grid>
        <Button Content="Control Template" Foreground="Wheat" >
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <Ellipse Width="120" Height="120" Fill="Gray" Name="grayOuterCircle" />
                        <Ellipse Width="100" Height="100" Name="gradiantInnerCircle">
                            <Ellipse.Fill>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                                    <GradientStop Color="Blue" Offset="0" />
                                    <GradientStop Color="Green" Offset="0.5" />
                                    <GradientStop Color="Red" Offset="1.0" />
                                </LinearGradientBrush>
                            </Ellipse.Fill>
                        </Ellipse>
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="grayOuterCircle" Property="Fill" Value="CadetBlue"></Setter>
                            <Setter TargetName="grayOuterCircle" Property="Cursor" Value="Hand"></Setter>
                            <Setter TargetName="gradiantInnerCircle" Property="Cursor" Value="Hand"></Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </Grid>
</Window>


Hover the mouse


6) Some Other Example


<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Grid>
        <Button Content="Control Template" Foreground="Wheat" Name="btn" >
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <Ellipse Width="120" Height="120" Fill="Gray" Name="grayOuterCircle" />
                        <Ellipse Width="100" Height="100" Name="gradiantInnerCircle">
                            <Ellipse.Fill>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                                    <GradientStop Color="Blue" Offset="0" />
                                    <GradientStop Color="Green" Offset="0.5" />
                                    <GradientStop Color="Red" Offset="1.0" />
                                </LinearGradientBrush>
                            </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="grayOuterCircle" Property="Fill" Value="CadetBlue"></Setter>
                            <Setter TargetName="grayOuterCircle" Property="Cursor" Value="Hand"></Setter>
                            <Setter TargetName="gradiantInnerCircle" Property="Cursor" Value="Hand"></Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </Grid>
</Window>


7) Binding with ViewModel Property


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace MVVMBasics
{
    public class Employee
    {
        public string EmpName { get; set; }
    }
    /// <summary>
    /// Interaction logic for ControlTemplateDemo.xaml
    /// </summary>
    public partial class ControlTemplateDemo : Window, INotifyPropertyChanged
    {
        public ControlTemplateDemo()
        {
            InitializeComponent();
            this.DataContext = this;
            EmpName = "View Model";
        }

        private string empName;
        public string EmpName
        {
            get
            {
                return empName;
            }
            set
            {
                empName = value;
                OnPropertyChanged("EmpName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler propChange = PropertyChanged;
            if (propChange != null)
            {
                propChange(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}


<Window x:Class="MVVMBasics.ControlTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlTemplateDemo" Height="200" Width="300">
    <Grid>
        <Button Content="Control Template" Foreground="Wheat" Name="btn" >
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <Ellipse Width="120" Height="120" Fill="Gray" Name="grayOuterCircle" />
                        <Ellipse Width="100" Height="100" Name="gradiantInnerCircle">
                            <Ellipse.Fill>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                                    <GradientStop Color="Blue" Offset="0" />
                                    <GradientStop Color="Green" Offset="0.5" />
                                    <GradientStop Color="Red" Offset="1.0" />
                                </LinearGradientBrush>
                            </Ellipse.Fill>
                        </Ellipse>
                        <TextBox Width="92" Height="30" Text="{Binding EmpName}"></TextBox>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="grayOuterCircle" Property="Fill" Value="CadetBlue"></Setter>
                            <Setter TargetName="grayOuterCircle" Property="Cursor" Value="Hand"></Setter>
                            <Setter TargetName="gradiantInnerCircle" Property="Cursor" Value="Hand"></Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </Grid>
</Window>



Data Template

Data Template is enable wpf change the appearance how the data should look for Collection of data, it is mostly used with Item Controls such as List Box, Combo box, List view, Data Grid


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace MVVMBasics
{
    public class Employee
    {
        public string EmpName { get; set; }
        public string Department { get; set; }
    }
    /// <summary>
    /// Interaction logic for DataTemplateDemo.xaml
    /// </summary>
    public partial class DataTemplateDemo : Window, INotifyPropertyChanged
    {
        public DataTemplateDemo()
        {
            InitializeComponent();
            EmpList = new ObservableCollection<Employee>();
            EmpList.Add(new Employee()
                {
                    EmpName = "Aman",
                    Department = "HR",
                });
            EmpList.Add(new Employee()
            {
                EmpName = "Kishan",
                Department = "IT",
            });
            EmpList.Add(new Employee()
            {
                EmpName = "Raman",
                Department = "IT",
            });
            EmpList.Add(new Employee()
            {
                EmpName = "Pinki",
                Department = "HR",
            });
            EmpList.Add(new Employee()
            {
                EmpName = "Reena",
                Department = "Sales",
            });
            this.DataContext = this;
        }

        private ObservableCollection<Employee> empList;
        public ObservableCollection<Employee> EmpList
        {
            get
            {
                return empList;
            }
            set
            {
                empList = value;
                OnPropertyChanged("EmpList");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler propChange = PropertyChanged;
            if (propChange != null)
            {
                propChange(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}




<Window x:Class="MVVMBasics.DataTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataTemplateDemo" Height="400" Width="300" Background="Gray">
    <Grid>
        <ListBox ItemsSource="{Binding EmpList}" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50*"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Label Content="Name : " Grid.Column="0" Grid.Row="0"></Label>
                        <Label Content="Department : " Grid.Column="0" Grid.Row="1"></Label>
                        <Label Content="{Binding EmpName}" Grid.Column="1" Grid.Row="0"></Label>
                        <Label Content="{Binding Department}" Grid.Column="1" Grid.Row="1"></Label>
                        <Separator Grid.Row="2" Grid.ColumnSpan="2" Background="Black" />
                    </Grid>

                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

In Windows Resource

<Window x:Class="MVVMBasics.DataTemplateDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataTemplateDemo" Height="400" Width="300" Background="Gray">
    <Window.Resources>
        <DataTemplate x:Key="listBoxDataTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Label Content="Name : " Grid.Column="0" Grid.Row="0"></Label>
                <Label Content="Department : " Grid.Column="0" Grid.Row="1"></Label>
                <Label Content="{Binding EmpName}" Grid.Column="1" Grid.Row="0"></Label>
                <Label Content="{Binding Department}" Grid.Column="1" Grid.Row="1"></Label>
                <Separator Grid.Row="2" Grid.ColumnSpan="2" Background="Black" />
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding EmpList}" ItemTemplate="{StaticResource listBoxDataTemplate}" >
        </ListBox>
    </Grid>
</Window>

Inside the ItemTemplate there are "DataTemplate", "HierarchicalDataTemplate"and "ItemContainerTemplate"