WPF DataGrid: Stock and Template Columns


The DataGrid uses a set of DataGridColumns to describe how to display its data just like a GridView has a set of GridViewColumns to describe its data.  In my first post, the sample I used auto-generated the columns for you but this time I want to go over how to create the columns manually.   

Column Types

Currently in our WPF DataGrid we have four available stock columns and a template column:

·         DataGridTextColumn

·         DataGridCheckBoxColumn

·         DataGridComboBoxColumn

·         DataGridHyperlinkColumn 

·         DataGridTemplateColumn

Each column type corresponds to the UIElement that it will show in each of the cells in that column.  The DataGridTemplateColumn allows you to customize the template with a custom UIElement or tree of Elements for each of the cells in the column.  Template columns derive from DataGridColumn, whereas stock columns derive from DataGridBoundColumn which derives from DataGridColumn. 

Why the difference in inherited classes?  The main difference is that a DataGridBoundColumn includes the property Binding, which is a convenience property for mapping a data item property in the ItemsSource to its corresponding set of cells in the column.  Here is an example: 

<dg:DataGridTextColumn Binding="{Binding Path=FirstName}" />


The concept is basically the same as setting the DisplayMemberBinding property on a GridViewColumn of a GridView.  I also talked about this in my post, Dissecting the Visual Layout.  For a DataGridTemplateColumn, since you are free to set the template to whatever you like, we cannot automatically figure out where you would like to place the binding.  Because of that, you are required to setup the binding yourself and therefore the class does not derive from DataGridBoundColumn.    

Stock Columns and styling

For stock columns or DataGridBoundColumns, the main properties you will likely use are the Binding property, which I describe above, and the Header property.  Header is just like GridViewColumn.Header, which displays the text on the DataGridColumnHeader of that column.

<dg:DataGridTextColumn Header="First Name" Binding="{Binding Path=FirstName}" />


Styling a stock column can be accomplished with these particular properties:

·         CellStyle

·         EditingElementStyle

·         ElementStyle 

Recall in my post, Dissecting the Visual Layout, when the DataGridCell is created its Content property is set after asking DataGridColumn to generate the visual tree.  Well, depending if you are in an editing state or not, the column will generate a different UIElement for each state.  For a DataGridTextColumn in an editing state, a TextBox is created.  In a non-editing state, a TextBlock is created.  For a DataGridComboBoxColumn in an editing state, a ComboBox is created, while in a non-editing state, a TextBlock is created.

With that in mind, CellStyle is the style for the overall DataGridCell (which is a ContentControl and items container), EditingElementStyle is the style for the DataGridCell’s Content generated during the editing state and ElementStyle is the style for the DataGridCell’s Content generated during the non-editing state.  Here is an example:       

<dg:DataGridTextColumn Header="First Name" Binding="{Binding Path=FirstName}">


    <Style TargetType="{x:Type dg:DataGridCell}">

      <Setter Property="Foreground" Value="Blue" />

      <Setter Property="FontWeight" Value="Bold" />





    <Style TargetType="TextBox">

      <Setter Property="Foreground" Value="Red" />





    <Style TargetType="TextBlock">

      <Setter Property="Foreground" Value="LightBlue" />





You should note that the Bold FontWeight will be applied to both the editing and non-editing element while the Foreground property set in CellStyle will be overwritten by the Foreground property set by each of the element styles.

Template Columns

For DataGridTemplateColumns, the Header and CellStyle property still apply but there isn’t a Binding, EditingElementStyle, or ElementStyle property.  Instead, you have the properties, CellTemplate and CellEditingTemplate.  DataGridCell’s Content generation is still the same; it’s just that it uses these two cell templates to generate the content instead.  Here is an example:

<dg:DataGridTemplateColumn Header="First Name">



      <Button Content="{Binding Path=FirstName}" />






      <TextBox Text="{Binding Path=FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />





In a non-editing state a Button is created as the UIElement for the cell and is bound to the FirstName property of my data source.  In an editing state a TextBox is created as the UIElement.  Having an editable Button in a DataGrid may not be a common scenario but I did want to show both CellTemplate and CellEditingTemplate.  If you do not want to make it editable, one thing you can do is just not declare the CellEditingTemplate.  Notice in both templates I setup the binding myself since I do not have a Binding like DataGridBoundColumns. 

Important: Also notice that in CellEditingTemplate I had to declare the binding with Mode set to TwoWay and UpdateSourceTrigger set to PropertyChanged.  This is another consequence of not getting the binding utilities that DataGridBoundColumns provide.  In a DataGridBoundColumn, when cells are edited and committed, the DataGrid will take care of updating the sources for you.  In the case of the template column, you will have to update the source yourself.  This issue is only for a commit scenario.  The DataGrid will still be able to rollback on a cancel command. 

Sizing Columns

Column sizing uses a special class called DataGridLength that has sizing properties specifically for a row and column scenario.  The types of widths are as follows:

·         Pixel

·         SizeToCells

·         SizeToHeader

·         Auto

·         Star

 Pixel uses absolute sizing on the column width, SizeToCells sizes the column width to the largest cell, SizeToHeader sizes the column width to the header width, Auto sizes the column width to either the largest cell or the header width whichever is larger, and Star sizing follow the proportional sizing like a Grid panel.  See the final example below for usage of the different widths.

Putting it all together

So with all that, I have updated the sample from my first post on DataGrid with what I discuss here.  Instead of auto-generating the columns, I’ve explicitly declared each column and I’ve setup different widths for you to get an idea of how that works.  You can also double-click on the column header grippers to change the width to Auto.  This functionality is similar to Windows Explorer.  I’ve also created a template column that displays an Image UIElement when in non-edit mode and a CombBox UIElement when in editing mode.  Notice the differences in how I setup the data bindings between the template column versus the bound columns.  I’ve also added a DataGridCell style and DataGridRow style that updates the BorderBrush and BorderThickness when in edit mode.  You can download the sample here. 

<Style x:Key="defaultCellStyle" TargetType="{x:Type dg:DataGridCell}">


      <Trigger Property="IsEditing" Value="True">

          <Setter Property="BorderBrush" Value="Red" />

          <Setter Property="BorderThickness" Value="2" />





<dg:DataGrid AutoGenerateColumns="False" CellStyle="{StaticResource defaultCellStyle}" …>


      <dg:DataGridTextColumn Width="130" Header="First Name" Binding="{Binding Path=FirstName}" />


      <dg:DataGridTextColumn Width="Auto" Header="Last Name" Binding="{Binding Path=LastName}" />


      <dg:DataGridCheckBoxColumn Width="SizeToCells" Header="Likes Cake" Binding="{Binding Path=LikesCake}" />


      <dg:DataGridComboBoxColumn Width="200" Header="Cake" SelectedItemBinding="{Binding Path=Cake}">









      <dg:DataGridHyperlinkColumn Width="SizeToHeader" Header="Homepage" Binding="{Binding Path=Homepage}" />


      <dg:DataGridTemplateColumn MaxWidth="250" Header="Picture">



                       <Image Source="{Binding Path=Picture}" />





                       <ComboBox SelectedItem="{Binding Path=Picture, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">



                                     <sys:String>Assets\Autumn Leaves.jpg</sys:String>


                                     <sys:String>Assets\Green Sea Turtle.jpg</sys:String>










More Related Material:

Dissecting the Visual Layout

Working with DataGridComboBoxColumn (Part1)

Working with DataGridComboBoxColumn (Part2)

Overview of the editing features in the DataGrid

Other Samples:

ScrollViewer with ToolTip

Custom sorting, column selection, single-click editing

Tri-state sorting



Comments (28)
  1. Link Listing – August 19, 2008

  2. pan says:

    This was a great help for a first touch with the DataGrid!

    I have a question: How can I specify the DataGridComboBoxColumn parameters when I have an ID-field for the DataFieldBinding and the combo box should display the content of an associated table?



  3. DataGridComboBoxColumn is a column that deserves some special attention. What makes it a little unique

  4. There have been several questions on the WPF CodePlex discussion list relating to styling rows and columns

  5. Introduction I’m going to talk a little on the editing features of the DataGrid. I will dive deep into

  6. hempels says:

    Having trouble seeing how I can go about adding a tooltip to the ElementStyle for a textblock in a text column:

    <dg:DataGridTextColumn Width="8.5*" Header="Key" DataFieldBinding="{Binding Key}">


       <Style TargetType="TextBlock">

         <Setter Property="ToolTip" Value="{Binding Text, ElementName=TextBlock}" />




  7. hempels,

    If you want to bind to the Text property on the TextBlock itself you can do something like this,

    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text}" />

  8. Frank says:


    I tried to select a template based on the data which is displayed by using a DataGridTemplateColumn with a CellTemplateSelector.

    But somehow the template is not selected correcly once the datagrid is scrolled.

    It seems that the template is only selected once and only for the data which initially fits into the grid.

    Any clues?


  9. Frank,

    There was a bug similar to this that was fixed in the v1 DataGrid.  Try your code out with those bits and let me know if you are still having issues.  More info on the v1 DataGrid here, http://blogs.msdn.com/vinsibal/archive/2008/10/22/wpf-datagrid-and-the-wpftoolkit-have-released.aspx

  10. David says:

    If I set Width to ‘Auto’ or ‘SizeToHeader’, the columns are very narrow.  If I use ‘SizeToCells’ the width seems to be correct.  My expectation is that Auto would set column width to the max of the width necessary to display cells or width necessary to display title.  Is this correct?

  11. David,

    Auto will set it to either SizeToHeader or SizeToCells, whichever is larger.  Is that not what you are seeing?

  12. Vinit says:

    Hi Vinsibal,

    Do you have any link or tips regarding sorting DataGridTemplateColumns?

    I see that for template column, although CanUserSort is True, the column header based sorting wouldnt appear. What could we possibly do to achieve this?

    Thx a lot for all the WPF help as always…

    – Vinit

  13. Vinit,

    What about setting the SortMemberPath on the DataGridTemplateColumn?

  14. Since the release of the WPF DataGrid there have been several common patterns of questions that developers

  15. Anurag says:

    thanks a lot, i was looking for it from several days 🙂

  16. Chander Shekhar says:

    Hi all

    I am trying to make a selected data row editable and change all the cells to their respective edit templayed on a button click

    can anyone help with this.

    Thanks in advance

  17. kapil bhavsar says:

    DataGrid column width remains large after decreasing font size even if the ColumnWidth is set to SizeToCell.

  18. Ranu says:

    Thanks a lot.

    I was looking for pasting an image into my DataGrid. Your tip about the "DataGridTemplateColumn" helped me. With the GenerateAutoColumns=True flag, the Toolkit automatically constructs TextColumns, so my image was shown as "System.Windows.Controls.Image" …

    With best regards,


  19. Chris says:

    I’m wondering on how I can dynamically add Columns to the WPF DataGrid? I see you can add to the column collection however I cannot instantiate a new column. How would one go about doing this or do you have a post to refer me to?

  20. Chris says:

    Oops I was instantiating the base DataGridColumn instead of DataGridTextColumn. Thanks anyways!

  21. Neil says:

    Hello, there is a lot of good information here, but I was wondering if you could help me with something. I’m trying to change the Style of a DataGridRow based on the databound value of a DataGridTextColumn in the row. Is there a way to write a trigger for the whole row that is based on the value of the contents of one of the cells in the row?

    For instance, the first column in the row is ‘Status’ and when the databinding changes the value to ‘ON’ I want the whole row to light up green. Etc.

    Any help or points in the right direction would be greatly appreciated. Thanks.


  22. Neil says:

    Nevermind, figured it out, thanks!

  23. saru says:


    your post is really helpful.Thanks

    I have a problem i want to show Row with CornerRadius so that i created one style as below.the border is ok but i cant see Values on the row even i bind the data.Please help me out and correct me.

     <Style x:Key="DataGridRowStyle" TargetType="{x:Type WpfToolkit:DataGridRow}">

               <Setter Property="Header" Value="{Binding Id}"/>

               <Setter Property="SnapsToDevicePixels" Value="true"/>

               <Setter Property="OverridesDefaultStyle" Value="true"/>

               <Setter Property="HorizontalContentAlignment" Value="Center" />

               <Setter Property="VerticalContentAlignment" Value="Center" />

               <Setter Property="Foreground" Value="#000000"/>

               <Setter Property="Height" Value="25"/>

               <Setter Property="Template">


                       <ControlTemplate TargetType="{x:Type WpfToolkit:DataGridRow}">


                                   Name="Border" Padding="2" SnapsToDevicePixels="true" Background="Red"

                                   CornerRadius="4" Margin="5,0,5,0">



                                     DataContext="{Binding Path=TemplatedParent.View.Columns,

                                                       RelativeSource={RelativeSource TemplatedParent}}"

                                   SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"

                                   Background="Chocolate" />                    



                               <Trigger Property="ItemsControl.AlternationIndex" Value="1">

                                   <Setter Property="Background" TargetName="Border"  Value="#A5FFFFFF"></Setter>


                               <Trigger Property="ItemsControl.AlternationIndex" Value="2">

                                   <Setter Property="Background" TargetName="Border"  Value="Red"></Setter>


                               <Trigger Property="IsSelected" Value="true">

                                   <Setter Property="Background" TargetName="Border" Value="#99B4C6"/>

                                   <Setter Property="Foreground" Value="#000000"/>


                               <Trigger Property="IsMouseOver" Value="true">

                                   <Setter Property="Background" TargetName="Border" Value="#c5d7e5"/>

                                   <Setter Property="Foreground" Value="#000000"/>


                               <Trigger Property="IsEnabled" Value="false">

                                   <Setter Property="Foreground" Value="#000000"/>






    Thank you,


  24. Francesco says:

    In your sample, how can I set foreground white in the HomePage column when I select the row?

    So, for example, if I use a TemplateColumn with a TextBox and not a DataGridTextColumn, how can I set a different foreground if the row is selected?

  25. Shrads says:

    Hi..I wanted 2 know how to reflect the changes in a particular datatemplate column when the rows in the datagrid are multiselected  and a particular cell in that column has changed.The cells in the datatemplate column which have been multiselected have to be updated if any of the cells have been changed..Do u have any solution for this??

  26. Klaus Wiesel says:


    In your example regarding "Template Columns" you are using the property "FirstName" as the binding for a textbox in the template column’s celleditingtemplate.

    In my app I have multiple template columns and I search for a way to get the property to which the textbox is bound (I have a handle to the template column)

    Can you post a sample of how to do this, as I using <celltemplate>.FindName gives me a compile error



Comments are closed.

Skip to main content