WPF Toolkit DataGrid, Part II – Custom styling
This post is part of the WPF Toolkit DataGrid series. Here is a list with the complete set of blog posts:
- Part I – Introduction
- Part II – Custom Styling
Introduction
In Part I we went through basic DataGrid setup creating a sample application that showcased the usage of DataGridColumns. In this part we will dive into more advanced concepts. It is my ambition that you get a good understanding of how to setup a DataGrid to do whatever you wish without restrictions. In this part we will focus on restyling the DataGrid, DataGridColumnHeaders and DataGridRowHeaders.
Roadmap
- Visual breakdown of styles and layout
- Styling the DataGrid
- Styling DataGridColumnHeaders
- Styling DataGridRowHeaders
- Creating a new template for the SelectAllButton
Download sample source code
Here is a list with the samples presented on this blog post:
- WPF Toolkit DataGrid Sample 03 – Styling the DataGrid
- WPF Toolkit DataGrid Sample 04 – Styling DataGridColumnHeaders
- WPF Toolkit DataGrid Sample 05 – Styling DataGridRowHeaders
- WPF Toolkit DataGrid Sample 06 – Styling the SelectAllRows button
Visual breakdown of layout and styles
Before we start digging dipper into DataGrid’s functionalities and restyling let’s take a look on what WPF Toolkit uses to build it. It is essential that you understand what each class is responsible for in order to find which styles you need to replace so that you can change the looks of a specific region of the DataGrid.
First let’s look at the DataGrid from a layout perspective. Along with the DataGrid this are the main components used to display the information inside of it:
These classes are the ones used by the DataGrid to render itself. They are the objects that end up on the application’s visual tree:
- DataGridColumnHeadersPresenter: this control will go through the DataGridColumns collection of the DataGrid and create a DataGridColumnHeader for each;
- DataGridColumnHeader: picks up the information in its DataGridColumn and renders it as a header on the corresponding column position;
- DataGridRowsPresenter: the ItemsControl that iterates the ItemsSource creating a DataGridRow for each item;
- DataGridRow: represents an item of ItemsSource;
- DataGridRowHeader: this is a Button that lays on the beginning of each DataGridRow. It allows the user to select the row, resize it, and can be used to show information – for instance, on the current operation being performed over the selected row or still to provide error information;
- DataGridCellsPresenter: this is the ItemsControl used to render each cell, based on the column bindings, for the DataGridRow bounded item;
- DataGridCell: this is the control used to render a specific value of an Item. Essentially it is made of two templates, one to display the item and one for editing it;
- DataGridDetailsPresenter: this is an extension of the DataGridRow used to show further information about a row than the one displayed by the cells. It is a panel that is normally laid bellow the cells. On WPF Toolkit’s DataGrid, by default, this panel is only shown when the user selects a row.
On the following image you can see where each of this controls are laid. Take some time to get to know what component is responsible for what part of the DataGrid.
Starting from the top, in the DataGrid, we will have a DataGridColumnHeadersPresenter used to present all DataGridColumnHeaders, there will be one header per bounded column. Each column header has two grippers. Inside the DataGrid along with the DataGridColumnHeadersPresenter there will be a DataGridRowsPresenter which will contain all our rows. The DataGridRow will contain a DataGridRowHeader and a DataGridCellsPresenter which contains all the DataGridCells. Also part of the DataGridRow, although not shown in the screenshot, is the DataGridDetailsPresenter, which can be used to present further details on the selected row.
If you use Snoop to browse the visual tree of our sample from Part I you will see the following (I have marked in red the items you should pay more attention to):
Side note: Snoop is a great tool for analyzing how a WPF application is structured. If you do not have this tool on you arsenal, stop reading, go to their web site, download it and install it. This is a must have if you are developing WPF applications.
You can see each of the classes we looked at above in the visual tree of our WPF sample application. Take some time to assimilate the structure used before proceeding.
By now you should have a solid understanding about the structure of the DataGrid. You should be able to easily spot each component along with which class is responsible for rendering it. This is the foundation for our next job – restyling the WPF Toolkit’s DataGrid.
Styling the DataGrid
Since the DataGrid is divided in several parts and each has individual styles, our ControlTemplate for it will not change that much, most of it will be based on the one that comes with WPF Toolkit.
The DataGrid style has five major components:
- Select all button: this is the button on the top left corner of the DataGrid that is used to select all rows;
- PART_ColumnHeadersPresenter: this is the ItemsControl used to present all of our DataGridColumnHeaders;
- PART_ScrollContentPresenter: the main area of the DataGrid where all the DataGridRows will be rendered;
- PART_VerticalScrollBar: renders the vertical scroll bar of our ScrollViewer;
- PART_HorizontalScrollBar: renders the horizontal scroll bar of our ScrollViewer.
I have taken a screenshot from Snoop in order to show you how these parts fit together on visual tree:
In the last sample we worked with on Part I, you may have notice that the vertical scroll bar does not occupy the full height of the DataGrid. In our new style, we will make it fill that empty space. This is just a minor tweak in the default DataGrid ControlTemplate.
Since you may want to reuse this new style just add a new resource dictionary to your solution where you can place the new DataGrid style – in the sample code I have named it ‘DataGrid.Generic.xaml’ and placed it under the Themes folder.
The change we are planning to make is a small one, so we can reuse the style defined within WPF Toolkit, you just have to copy the DataGrid style from the ‘Generic.xaml’ file on WPF Toolkit and add it to your new dictionary. Find the definition of the vertical scroll bar in the ControlTemplate part of the style. Change Grid.Row to 0 and give it a Grid.RowSpan of 2, as shown below:
(…) <ScrollBar Name="PART_VerticalScrollBar" Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" Orientation="Vertical" Maximum="{TemplateBinding ScrollableHeight}" ViewportSize="{TemplateBinding ViewportHeight}" Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/> (…)
Along with extending the scroll bar you can also style your DataGrid by setting some nice colors. To give your DataGrid a cooler look you can start by creating a series of brushes:
<!-- Generic brushes --> <SolidColorBrush x:Key="DefaultControlBorderBrush" Color="#FF688CAF"/> <SolidColorBrush x:Key="DefaultControlBackgroundBrush" Color="#FFE3F1FE"/> <SolidColorBrush x:Key="DefaultControlForegroundBrush" Color="#FF10257F"/> <!-- DataGrid related brushes --> <SolidColorBrush x:Key="GridLineColorBrush" Color="#FFCEDFF6" /> <LinearGradientBrush x:Key="AlternateRowBackgroundBrush" StartPoint="0.5,0.0" EndPoint="0.5,1.0"> <GradientStop Color="#FFFEFEFF" Offset="0"/> <GradientStop Color="#FFE4F0FC" Offset="1"/> </LinearGradientBrush>
(…) <Setter Property="Background" Value="{StaticResource DefaultControlBackgroundBrush}"/> <Setter Property="Foreground" Value="{StaticResource DefaultControlForegroundBrush}"/> <Setter Property="BorderBrush" Value="{StaticResource DefaultControlBorderBrush}" /> <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource GridLineColorBrush}" /> <Setter Property="VerticalGridLinesBrush" Value="{StaticResource GridLineColorBrush}" /> <Setter Property="AlternatingRowBackground" Value="{StaticResource AlternateRowBackgroundBrush}" /> <Setter Property="BorderThickness" Value="1" /> (…)
In the sample you will find all the style for the DataGrid. When you go through its ControlTemplate you will see most of the items described in ‘Visual breakdown of layout and styles’. This is how our DataGrid currently looks with the new style:
You can download a working sample by following this link.
Styling DataGridColumnHeaders
The next step will be to create custom styles for our DataGridColumnHeaders. In the class diagram above you can see that DataGridColumnHeaders extend ButtonBase, so when we style a DataGridColumnHeader we are actually creating a style for a button. We also need to keep in mind the two styles for the grippers – one for each side of the DataGridColumnHeader. The grippers will be used to resize the DataGridColumnHeader, thus they need to exist as controls the user can interact with!
Let’s start by creating the style for the grippers, both left and right, since they will be referenced as static resources by the DataGridColumnHeader style.
<!-- DataGridColumnHeader Right Gripper Style --> <Style x:Key="ColumnHeaderRightGripperStyle" TargetType="{x:Type Thumb}"> <Setter Property="Width" Value="8"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="Cursor" Value="SizeWE"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Thumb}"> <Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}"> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- DataGridColumnHeader Left Gripper Style --> <Style x:Key="ColumnHeaderLeftGripperStyle" BasedOn="{StaticResource ColumnHeaderRightGripperStyle}" TargetType="{x:Type Thumb}"> <Setter Property="Width" Value="8"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="Cursor" Value="SizeWE"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Thumb}"> <Border Name="Border" Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}"> <Canvas> <Line RenderOptions.EdgeMode="Aliased" Stroke="#88B0E4" X1="7" Y1="{Binding ElementName=Border, Path=ActualHeight}" X2="7" Y2="0"/> </Canvas> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
As you may have noticed we are drawing a line on the left gripper but not drawing it on the right gripper. If we were to draw lines on both sides the end result would be a thicker line. Instead, on the right gripper, we just reserve some space so that the user will have somewhere to click and drag to resize the column.
Now that you have created the grippers you can go ahead and create the style for the DataGridColumnHeader. In this style we will be adding a nice blue gradient background and a highlight gradient that gets displayed when the user put his mouse over a column header:
<!-- DataGridColumnHeader Style --> <Style x:Key="ColumnHeaderStyle" TargetType="{x:Type WpfToolkit:DataGridColumnHeader}"> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}"/> <Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" /> <Setter Property="BorderThickness" Value="0,1,0,1" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type WpfToolkit:DataGridColumnHeader}"> <Grid> <WpfToolkit:DataGridHeaderBorder x:Name="headerBorder" SortDirection="{TemplateBinding SortDirection}" IsHovered="{TemplateBinding IsMouseOver}" IsPressed="{TemplateBinding IsPressed}" IsClickable="{TemplateBinding CanUserSort}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding ="{TemplateBinding Padding}" SeparatorVisibility="{TemplateBinding SeparatorVisibility}" SeparatorBrush="{TemplateBinding SeparatorBrush}"> <Border BorderBrush="{StaticResource HeaderInnerBorderBrush}" BorderThickness="0,1,0,0"> <TextBlock Text="{Binding}" Margin="4,0,4,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" /> </Border> </WpfToolkit:DataGridHeaderBorder> <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderRightGripperStyle}"/> <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderLeftGripperStyle}"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="headerBorder" Property="Background" Value="{StaticResource HeaderHighlightedBackgoundBrush}" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter TargetName="headerBorder" Property="Background" Value="{StaticResource HeaderPressedBackgroundBrush}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
Go ahead now and create a ‘Brushes.xaml’ beside the ‘DataGrid.Generic.xaml’ resource dictionary. In here you will define all of the brushes used by the styles in the DataGrid. This will make it easier for you to reuse them on the remaining controls of your application.
<!-- Header related brushes --> <SolidColorBrush x:Key="HeaderBorderBrush" Color="#88B0E4"/> <SolidColorBrush x:Key="HeaderInnerBorderBrush" Color="#FFFFFF" /> <LinearGradientBrush x:Key="HeaderBackgroundBrush" StartPoint="0.5,0.0" EndPoint="0.5,1.0"> <GradientStop Color="#FF98BFEB" Offset="0"/> <GradientStop Color="#FFB8D4F2" Offset="1"/> </LinearGradientBrush> <LinearGradientBrush x:Key="HeaderHighlightedBackgoundBrush" StartPoint="0,0" EndPoint="0,1"> <GradientStop Color="#FFA3CBF7" Offset="0"/> <GradientStop Color="#FFD9E6F9" Offset="1"/> </LinearGradientBrush> <LinearGradientBrush x:Key="HeaderPressedBackgroundBrush" StartPoint="0,0" EndPoint="0,1"> <GradientStop Color="#FFA3CBF7" Offset="1"/> <GradientStop Color="#FFD9E6F9" Offset="0"/> </LinearGradientBrush>
<Setter Property="ColumnHeaderStyle" Value="{StaticResource ColumnHeaderStyle}"/>
Here are our fancy looking DataGridColumnHeaders. Notice that the ‘Player Name’ column was purposely highlighted when the screenshot was taken.
You can download a working sample of the code presented here by following this link.
Styling DataGridRowHeaders
DataGridRowHeaders pretty much follow the DataGridColumnHeaders in the way they are implemented. So you have two grippers, one on top and another on bottom, and a style for header itself. In this case we will use the same style for both the grippers just to lay the required space for the user to interact with. The visual separator for the columns will be the control template’s border.
<!-- DataGridRowHeader Gripper --> <Style x:Key="RowHeaderGripperStyle" TargetType="{x:Type Thumb}"> <Setter Property="Height" Value="8"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="Cursor" Value="SizeNS"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Thumb}"> <Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}"/> </ControlTemplate> </Setter.Value> </Setter> </Style>
Now you can go ahead and include the style for the DataGridRowHeader. For this you will use most of the code from the DataGridColumnHeader and the corresponding brushes. We want to keep the look and feel of both header types consistent.
<!-- DataGridRowHeader Style --> <Style x:Key="{x:Type WpfToolkit:DataGridRowHeader}" TargetType="{x:Type WpfToolkit:DataGridRowHeader}"> <Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}" /> <Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type WpfToolkit:DataGridRowHeader}"> <Grid> <WpfToolkit:DataGridHeaderBorder x:Name="headerBorder" IsSelected="{TemplateBinding IsRowSelected}" IsHovered ="{TemplateBinding IsMouseOver}" IsPressed="{TemplateBinding IsPressed}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,0,1,1" Padding ="{TemplateBinding Padding}" Orientation="Horizontal" SeparatorVisibility="{TemplateBinding SeparatorVisibility}" SeparatorBrush="{TemplateBinding SeparatorBrush}"> <Border BorderBrush="{StaticResource HeaderInnerBorderBrush}" BorderThickness="0,1,0,0"> <StackPanel Orientation="Horizontal"> <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/> <Control SnapsToDevicePixels="false" Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type WpfToolkit:DataGridRow}}, Path=(Validation.HasError), Converter={StaticResource bool2VisibilityConverter}}" Template="{Binding RelativeSource={RelativeSource AncestorType={x:Type WpfToolkit:DataGridRow}}, Path=ValidationErrorTemplate}" /> </StackPanel> </Border> </WpfToolkit:DataGridHeaderBorder> <Thumb x:Name="PART_TopHeaderGripper" VerticalAlignment="Top" Style="{StaticResource RowHeaderGripperStyle}"/> <Thumb x:Name="PART_BottomHeaderGripper" VerticalAlignment="Bottom" Style="{StaticResource RowHeaderGripperStyle}"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="headerBorder" Property="Background" Value="{StaticResource HeaderHighlightedBackgoundBrush}" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter TargetName="headerBorder" Property="Background" Value="{StaticResource HeaderPressedBackgroundBrush}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
It is looking pretty cool! To download the sample for this part of the tutorial just follow this link.
Creating a new template for the SelectAllButton
The only thing that is currently killing the look of our DataGrid is that top left corner button. This button is used to select all the rows on the DataGrid and its appearance can be altered by setting it on the DataGrid’s style. First you have to create the style for the button:
<!-- SelectAllButton ControlTemplate --> <ControlTemplate x:Key="SelectAllButtonTemplate" TargetType="{x:Type Button}"> <Grid> <Rectangle x:Name="Border" SnapsToDevicePixels="True" Stroke="{StaticResource HeaderBorderBrush}" Fill="{StaticResource HeaderBackgroundBrush}" /> <Border SnapsToDevicePixels="True" Margin="1,1,1,0" BorderBrush="White" BorderThickness="0,1,0,0" /> <Polygon x:Name="Arrow" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="8,8,3,3" Opacity="0.15" Fill="Black" Stretch="Uniform" Points="0,10 10,10 10,0" /> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="Border" Property="Fill" Value="{StaticResource HeaderHighlightedBackgoundBrush}" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter TargetName="Border" Property="Fill" Value="{StaticResource HeaderPressedBackgroundBrush}" /> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter TargetName="Arrow" Property="Visibility" Value="Collapsed" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate>
The only thing remaining now is to set this template on the corresponding button on the DataGrid style:
<!--Left Column Header Corner --> (...) <Button Command="{x:Static WpfToolkit:DataGrid.SelectAllCommand}" Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type WpfToolkit:DataGrid}}, Path=CellsPanelHorizontalOffset}" Focusable="false" Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type WpfToolkit:DataGrid}}, Path=HeadersVisibility, Converter={x:Static WpfToolkit:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static WpfToolkit:DataGridHeadersVisibility.All}}" Template="{StaticResource SelectAllButtonTemplate}"/> (...)
Congrats! You have now restyled all of the relevant components of the DataGrid. This is the final screenshot of the sample developed on this blog post:
End of Part II
In this part you have seen how to style the look of the DataGrid. You got to know a bit more about the structure used by WPF Toolkit to render its DataGrid and its data.
Don’t miss the next part of this series. We will look into more advanced stuff like styling cells, columns and creating custom DataGridColumns.

How would you set the mouse over event for the left & right column gripper to display when user resize the column?
Hi Jennifer,
I am not sure I understand what you are trying to accomplish, could you elaborate it a bit further so that I get a better picture of it?
Thanks!
Awesome! Thank you so much. I have a super nice datagrid now without having to spend days trying to figure it out
Really helpful for non-designer people.
Samuel
all grid elements are templated by your really nice solution … no wait,there is something missing: If the datagrid has only 2 columns for example, there is space left from the second column to the right border of the datagrid. And the column header area of this empty space is still “battleship grey”
I hope you understand my point, how can I retemplate/recolor this area?
Regards
Klaus
Samuel, I found it by myself: your answer from below is it
August 20th, 2009 at 23:18 | #13 Reply | Quote @JD
Its good to know that people can find answers in questions already answered. It makes the all commenting worth it!
@Mona Great to year that these articles have helped you out! Thank you so much for the lovely comment.
cool. Nice approach to styling.
A dumb question since I’m newbie: Why when I select a row I dont have highlighted with blue (like screenshots?).Is something missing in the resources? Thanks.
@dimipel
that is not an highlight. It is a background change for the selected row. Color depends on your Windows theme.
Up/down sorting arrows icons is missing in the column header.
@Roland True! I had remove them since I did not wanted to add support for sorting on this example. In any case it should be pretty straight forward to add them.
Here ist the solution for sort arrows: http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx
See “Styling the Column Header”
Great article and nice styling. Thanks for all the good work. Keep it up.
@Christoph Dreßler Thanks for sharing the link!
@Kish Thank you so much for the motivating feedback!
Hi there,
Great website, it’s helped me a lot. I’m wondering if you can possibly help me with an issue though. I’m using almost verbatim the same datagrid style you have defined above. My issue is, in my grid I have 3 columns that allow input(IsReadOnly=False) while the others don’t. I would like these 3 to have a different background color than the rest, while maintaining the gradient brush style, and the AlternatingRowBackground pattern.
For example, in your grid above, the rows alternate between white and a gradient light blue. I’d like to maintain this, except for the input fields would alternate between a really light green and a darker gradient green for example. Do you think this is possible? Thanks in advance!