Templating Elements

Glossary Item Box

The following page provides a list of examples that demonstrate how to template various elements. For more template-related information, refer to the Templates topic.

All examples in this topic assume that the grid is bound to the Orders table of the Northwind database, unless stated otherwise.

ShowProviding a cell-content template

The following example demonstrates how to provide a new CellContentTemplate, using property element syntax, for a boolean column that displays a check mark when the cell's value is true, and an "x" when it is false.

This example assumes that the grid is bound to the Products table of the Northwind database.

XAML Copy Code
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
  <Grid.Resources>
    <xcdg:DataGridCollectionViewSource x:Key="cvs_products"
                                    Source="{Binding Source={x:Static Application.Current},
                                                      Path=Products}"/>
  </Grid.Resources>
   <xcdg:DataGridControl x:Name="ProductsGrid"
                         ItemsSource="{Binding Source={StaticResource cvs_products}}">
      <xcdg:DataGridControl.Columns>
        <xcdg:Column FieldName="Discontinued">
           
<xcdg:Column.CellContentTemplate>
              
<DataTemplate>
                 
<Image x:Name="img" Source="D:\true.png" Stretch="None" />
                    
<DataTemplate.Triggers>
                       
<DataTrigger Binding="{Binding}" Value="False">
                         
<Setter TargetName="img" Property="Source" Value="D:\false.png" />
                       
</DataTrigger>
                    
</DataTemplate.Triggers>
              
</DataTemplate>
           
</xcdg:Column.CellContentTemplate>
        
</xcdg:Column>
      </xcdg:DataGridControl.Columns>
   </xcdg:DataGridControl>
</Grid>

ShowProviding a group-header control template

The following example demonstrates how to provide, through a style, a new GroupHeaderControl template.

XAML Copy Code
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
  <Grid.Resources>
    <Style TargetType="{x:Type xcdg:GroupHeaderControl}">
      
<Setter Property="Template">
        
<Setter.Value>
          
<ControlTemplate TargetType="{x:Type xcdg:GroupHeaderControl}">
            <Border Background="Orange" BorderThickness="2">
              <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding RelativeSource={RelativeSource
                                      TemplatedParent}, Path=Group.IsExpanded}"/>
                <ContentPresenter/>
              </StackPanel>
            </Border>
          </ControlTemplate>
        
</Setter.Value>
      
</Setter>
    
</Style>
    <xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
                                     Source="{Binding Source={x:Static Application.Current},
                                                      Path=Orders}">
      <xcdg:DataGridCollectionViewSource.GroupDescriptions>
        <xcdg:DataGridGroupDescription PropertyName="ShipCountry"/>
      </xcdg:DataGridCollectionViewSource.GroupDescriptions>
    </xcdg:DataGridCollectionViewSource>
  </Grid.Resources>
  <xcdg:DataGridControl x:Name="OrdersGrid"
                        ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>

ShowProviding a data-cell template

The following example demonstrates how to provide, through a style, a new ControlTemplate for the DataCells that will display the cells as buttons.

ImageTitle
Click to EnlargeClick to Enlarge
XAML Copy Code

<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
  <Grid.Resources>

    <Style TargetType="{x:Type xcdg:DataCell}">
      
<Setter Property="Template">
        
<Setter.Value>
          
<ControlTemplate TargetType="{x:Type xcdg:DataCell}">
            
<Button>
              
<Button.Content>
                
<ContentPresenter/>
              
</Button.Content>
            
</Button>
          
</ControlTemplate>
        
</Setter.Value>
      
</Setter>
    
</Style>

    <xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
                                    Source="{Binding Source={x:Static Application.Current},
                                                      Path=Orders}"/>
   </Grid.Resources>

   <xcdg:DataGridControl x:Name="OrdersGrid"
                         ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>

ShowProviding a data-row template

The following example demonstrates how to provide, through a style, a new ControlTemplate for DataRow objects. The columns that are contained in the grid will be limited to those specified in the ItemProperties of the DataGridCollectionViewSource.

This example assumes that the grid is bound to the Employees table of the Northwind database.

XAML Copy Code

<Grid>
 
<Grid.Resources>
   
<xcdg:DataGridCollectionViewSource x:Key="cvs_employees"
                                      
Source="{Binding Source={x:Static Application.Current},
                                                       
Path=Employees}">
     
<xcdg:DataGridCollectionViewSource.ItemProperties>
       
<xcdg:DataGridItemProperty Name="LastName"/>
       
<xcdg:DataGridItemProperty Name="FirstName"/>
       
<xcdg:DataGridItemProperty Name="Photo"/>
       
<xcdg:DataGridItemProperty Name="Title"/>
       
<xcdg:DataGridItemProperty Name="Notes"/>
       
<xcdg:DataGridItemProperty Name="EmployeeID"/>
       
<xcdg:DataGridItemProperty Name="TitleOfCourtesy"/>
       
<xcdg:DataGridItemProperty Name="HireDate"/>
       
<xcdg:DataGridItemProperty Name="Extension"/>
     
</xcdg:DataGridCollectionViewSource.ItemProperties>
   
</xcdg:DataGridCollectionViewSource>
   
<ControlTemplate x:Key="titleLessCell"
                    
TargetType="xcdg:DataCell">
     
<ContentPresenter Content="{xcdg:CellContentBinding}"
                       
ContentTemplate="{TemplateBinding ContentTemplate}"
                       
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"/>
   
</ControlTemplate>
   
<Style x:Key="customCardViewDataRow"
          
TargetType="{x:Type xcdg:DataRow}">
     
<Setter Property="Background"
             
Value="Transparent"/>
     
<Setter Property="Template">
       
<Setter.Value>
         
<ControlTemplate TargetType="{x:Type xcdg:DataRow}">
           
<Border x:Name="PART_RowFocusRoot"
                   
Background="{TemplateBinding Background}"
                   
BorderBrush="{TemplateBinding BorderBrush}"
                   
BorderThickness="{TemplateBinding BorderThickness}"
                   
Padding="{TemplateBinding Padding}">
             
<Grid>
               
<StackPanel>
                 
<DockPanel>
                   
<!-- The photo is at the left. -->
                   
<Grid DockPanel.Dock="Left"
                         
Margin="3,4,2,2"
                         
MaxWidth="85"
                         
MaxHeight="85">
                     
<xcdg:DataCell FieldName="Photo"
                                     
Template="{StaticResource titleLessCell}"/>
                   
</Grid>
                   
<StackPanel Margin="8,0,0,0">
                     
<StackPanel Orientation="Horizontal">
                       
<xcdg:DataCell FieldName="TitleOfCourtesy"
                                      
FontSize="16"
                                      
Template="{StaticResource titleLessCell}"/>
                       
<TextBlock Text=" "/>
                       
<xcdg:DataCell FieldName="FirstName"
                                      
FontSize="16"
                                      
Template="{StaticResource titleLessCell}"/>
                       
<TextBlock Text=" "/>
                       
<xcdg:DataCell FieldName="LastName"
                                      
FontSize="16"
                                      
Template="{StaticResource titleLessCell}"/>
                     
</StackPanel>
                      
<xcdg:DataCell FieldName="Title"
                                    
FontSize="14"
                                    
Template="{StaticResource titleLessCell}"/>
                       
<Border BorderThickness="1"
                               
BorderBrush="#999999"
                               
Margin="0,2,0,2"/>
                         
<StackPanel x:Name="PART_CellsHost"
                                     
Orientation="Vertical"
                                     
Grid.IsSharedSizeScope="True"/>
                   
</StackPanel>
                 
</DockPanel>
                 
<Expander Header="Notes"
                           
Padding="5"
                           
TextElement.Foreground="{TemplateBinding Foreground}">
                   
<xcdg:DataCell FieldName="Notes"
                                  
Template="{StaticResource titleLessCell}"/>
                 
</Expander>
               
</StackPanel>
             
</Grid>
           
</Border>
         
</ControlTemplate>
       
</Setter.Value>
     
</Setter>
     
<Setter Property="FocusVisualStyle"
             
Value="{x:Null}"/>
   
</Style>
 
</Grid.Resources>
 
<xcdg:DataGridControl x:Name="OrdersGrid"
                       
ItemsSource="{Binding Source={StaticResource cvs_employees}}"
                       
ItemContainerStyle="{StaticResource customCardViewDataRow}"
                       
View="CardView">
   
<xcdg:DataGridControl.Columns>
     
<xcdg:Column FieldName="Notes"
                  
TextWrapping="Wrap"/>
   
</xcdg:DataGridControl.Columns>
 
</xcdg:DataGridControl>
</
Grid>

ShowProviding an insertion-row template

The following example demonstrates how to provide, through a style, a new InsertionRow template. In order to preserve the fixed-column splitter in the insertion row, we need to use a FixedCellPanel as the "PART_CellsHost" template part.

XAML Copy Code
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
  <Grid.Resources>
    <xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
                                    Source="{Binding Source={x:Static Application.Current},
                                                        Path=Orders}"/>
   <Style x:Key="insertionrow_style"
          
TargetType="{x:Type xcdg:InsertionRow}">
     
<Setter Property="Template">
       
<Setter.Value>
         
<ControlTemplate TargetType="{x:Type xcdg:InsertionRow}">
            <Expander Header="Insert New Data">
              <Border BorderBrush="LightBlue"
                      BorderThickness="0, 1, 0, 1">
               <xcdg:FixedCellPanel x:Name="PART_CellsHost"
                  
FixedCellCount="{xcdg:ViewBinding FixedColumnCount, Mode=TwoWay}"
                  
SplitterStyle="{TemplateBinding xcdg:TableView.FixedColumnSplitterStyle}"
                  
SplitterWidth="{xcdg:ViewBinding FixedColumnSplitterWidth}"
                  
ShowSplitter="{xcdg:ViewBinding ShowFixedColumnSplitter}"
                  
FixedColumnDropMarkPen="{xcdg:ViewBinding FixedColumnDropMarkPen}"
                  
Background="LightBlue"/>
              </Border>
            </Expander>
         </ControlTemplate>
       
</Setter.Value>
     
</Setter>
   
</Style>
  </Grid.Resources>
  <xcdg:DataGridControl x:Name="OrdersGrid"
                        ItemsSource="{Binding Source={StaticResource cvs_orders}}">
    <xcdg:DataGridControl.View>
      <xcdg:TableView>
        <xcdg:TableView.FixedFooters>
         <DataTemplate>
           
<xcdg:InsertionRow Style="{StaticResource insertionrow_style}"/>
         
</DataTemplate>
        </xcdg:TableView.FixedFooters>
      </xcdg:TableView>
    </xcdg:DataGridControl.View>
  </xcdg:DataGridControl>    
</Grid>

ShowFormatting a cell's content

he following example demonstrates how to format a cell's content to display a numeric value as a currency value. Although it might be tempting to apply the converter to a column's DisplayMemberBinding, this is not the recommended location as not only will the cells' content be formatted but the data type of the cells' content will be changed to the converter's.

XAML Copy Code
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
      xmlns:local="clr-namespace:Xceed.Wpf.Documentation">
  <Grid.Resources>
    <xcdg:DataGridCollectionViewSource x:Key="cvs_orderdetails"
                                    Source="{Binding Source={x:Static Application.Current}, 
                                                      Path=OrderDetails}"/>           
           
    <local:CurrencyConverter x:Key="currencyConverter"/>

    
<DataTemplate x:Key="currency_celltemplate">
      
<TextBlock Text="{Binding Converter={StaticResource currencyConverter}}"/>
    
</DataTemplate>
  </Grid.Resources>

  <xcdg:DataGridControl x:Name="OrderDetailGrid"
                        ItemsSource="{Binding Source={StaticResource cvs_orderdetails}}">
    <xcdg:DataGridControl.Columns>
      <xcdg:Column FieldName="UnitPrice"
                   
CellContentTemplate="{StaticResource currency_celltemplate}"/>
    </xcdg:DataGridControl.Columns>
  </xcdg:DataGridControl>
</Grid>

The following code provides the implementation of the CurrencyConverter class used in the previous example.

VB.NET Copy Code

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Windows.Data
Imports System.Globalization
Namespace Xceed.Wpf.Documentation

  <ValueConversion(GetType(Double), GetType(String))> _
  Public Class CurrencyConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As Type, _
                          ByVal parameter As Object, ByVal culture As CultureInfo) As Object
      If (Not value Is Nothing) AndAlso ((Not Object.Equals(String.Empty, value))) Then
        Try
          ' Convert the string value provided by an editor to a double before formatting.
          Dim tempDouble As Double = System.Convert.ToDouble(value, _
                                                             CultureInfo.CurrentCulture)
          Return String.Format(CultureInfo.CurrentCulture, "{0:C}", tempDouble)
        Catch e1 As FormatException
        Catch e2 As OverflowException
        End Try
      End If
      Return String.Format(CultureInfo.CurrentCulture, "{0}", value)
    End Function
    Public Function ConvertBack(ByVal value As Object, _
                                ByVal targetType As Type, _
                                ByVal parameter As Object, _
                                ByVal culture As CultureInfo) As Object

      Return Double.Parse(TryCast(value, String), _
                          NumberStyles.Currency, _
                          CultureInfo.CurrentCulture)
    End Function
  End Class
End Namespace

C# Copy Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Globalization;
namespace Xceed.Wpf.Documentation
{
  [ValueConversion( typeof( double ), typeof( string ) )]
  public class CurrencyConverter : IValueConverter
  {
    public object Convert( object value, Type targetType,
                           object parameter, CultureInfo culture )
    {
      if( ( value != null ) && ( !object.Equals( string.Empty, value ) ) )
      {
        try
        {
          // Convert the string value provided by an editor to a double before formatting.
          double tempDouble = System.Convert.ToDouble( value, CultureInfo.CurrentCulture );
          return string.Format( CultureInfo.CurrentCulture, "{0:C}", tempDouble );
        }
        catch( FormatException )
        {
        }
        catch( OverflowException )
        {
        }
      }
      return string.Format( CultureInfo.CurrentCulture, "{0}", value );
    }
    public object ConvertBack( object value, Type targetType,
                               object parameter, CultureInfo culture )
    {
      return double.Parse( value as string, NumberStyles.Currency,
                           CultureInfo.CurrentCulture );
    }
  }
}

ShowChanging the group-header text

The following example demonstrates how to change the information displayed in each GroupHeaderControl by creating an implicit DataTemplate targeting the Group data type. 

XAML Copy Code

<Grid>
  <Grid.Resources>
    <xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
                                       Source="{Binding Source={x:Static Application.Current},
                                                        Path=Orders}">
      <xcdg:DataGridCollectionViewSource.GroupDescriptions>
        <xcdg:DataGridGroupDescription PropertyName="ShipCountry"/>
      </xcdg:DataGridCollectionViewSource.GroupDescriptions>
    </xcdg:DataGridCollectionViewSource>

    <DataTemplate DataType="{x:Type xcdg:Group}">
      
<StackPanel Orientation="Horizontal">
        
<TextBlock Text="The "/>
        
<TextBlock Text="{Binding Value}"/>
        
<TextBlock Text=" group contains "/>
        
<TextBlock Text="{Binding Items.Count}"/>
        
<TextBlock Text=" items."/>
      
</StackPanel>
    
</DataTemplate>

  </Grid.Resources>

  <xcdg:DataGridControl x:Name="OrdersGrid"
                        ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>