I recently converted a project from WPF 3.5 to WPF 4.0. Functionally, everything works, but the DataGrid style I was applying on top of the Aero theme has suddenly stopped working. As you can see from the before/after pictures below, my DataGrids went from having an Aero look plus bold headings, extra padding, and alternating row formats to just looking plain “Aero”. Besides removing all references to the WPF Toolkit (since the DataGrid is now native to WPF 4.0), I really didn’t change anything about my code/markup.
Before (WPF Toolkit DataGrid)

After (.NET 4.0 DataGrid)

As I learned in an earlier question, I am able to get the custom DataGrid styling to work again if I stop referencing the Aero resource dictionary, but then everything looks “Luna” on Windows XP (which is not what I want).
So, how do I ensure that my app always uses the Aero theme, but still apply styling on top of that theme in WPF 4.0?
Here is my App.xaml code:
<Application
x:Class="TempProj.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/PresentationFramework.Aero,
Version=3.0.0.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35,
ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" />
<ResourceDictionary Source="/CommonLibraryWpf;component/ResourceDictionaries/DataGridResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Here is my DataGridResourceDictionary.xaml code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="DataGrid_ColumnHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="TextBlock.TextWrapping" Value="WrapWithOverflow" />
</Style>
<Style x:Key="DataGrid_CellStyle" TargetType="DataGridCell">
<Setter Property="Padding" Value="5,5,5,5" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="DataGrid">
<Setter Property="ColumnHeaderStyle" Value="{StaticResource DataGrid_ColumnHeaderStyle}" />
<Setter Property="CellStyle" Value="{StaticResource DataGrid_CellStyle}" />
<Setter Property="Background" Value="White" />
<Setter Property="AlternatingRowBackground" Value="#F0F0F0" />
<Setter Property="VerticalGridLinesBrush" Value="LightGray" />
<Setter Property="HeadersVisibility" Value="Column" />
<Setter Property="SelectionMode" Value="Single" />
<Setter Property="SelectionUnit" Value="FullRow" />
<Setter Property="GridLinesVisibility" Value="Vertical" />
<Setter Property="AutoGenerateColumns" Value="False" />
<Setter Property="CanUserAddRows" Value="False" />
<Setter Property="CanUserDeleteRows" Value="False" />
<Setter Property="CanUserReorderColumns" Value="True" />
<Setter Property="CanUserResizeColumns" Value="True" />
<Setter Property="CanUserResizeRows" Value="False" />
<Setter Property="CanUserSortColumns" Value="True" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderBrush" Value="#DDDDDD" />
<Setter Property="HorizontalGridLinesBrush" Value="#DDDDDD" />
<Setter Property="VerticalGridLinesBrush" Value="#DDDDDD" />
</Style>
<Style x:Key="DataGrid_FixedStyle" TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="CanUserReorderColumns" Value="False" />
<Setter Property="CanUserResizeColumns" Value="False" />
<Setter Property="CanUserResizeRows" Value="False" />
<Setter Property="CanUserSortColumns" Value="False" />
</Style>
</ResourceDictionary>
Here’s a usage sample:
<DataGrid
Grid.Row="0"
Grid.Column="0"
Style="{StaticResource DataGrid_FixedStyle}"
ItemsSource="{Binding Coordinates}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding X}" Header="X" />
<DataGridTextColumn Binding="{Binding Y}" Header="Y" />
<DataGridTextColumn Binding="{Binding Z}" Header="Z" />
</DataGrid.Columns>
</DataGrid>
Edit
It just occurred to me that maybe the problem is that I’m referencing the wrong version of the Aero framework.
Here’s what I have now:
<ResourceDictionary
Source="/PresentationFramework.Aero,
Version=3.0.0.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35,
ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" />
Should this be updated to version 4.0? What is the PublicKeyToken for version 4 (or how do I figure this out)?
Relatively Short Answer
Loading a theme’s resources is not the same as changing the theme at the OS level. Loading a theme’s resources may cause adverse effects. From WPF’s point of view, a large number of implicit Styles are now present in the application. These Styles may trump other Styles. The bottom line is treating a theme like an application skin may not work without refinements.
There are some alternative ways of simulating a theme change.
This problem showcases some fairly complex WPF functionality, and a portion of it appears to be undocumented. However, it does not appear to be a bug. If it’s not a bug – that is, if all of it is intentional WPF behavior – you might well argue the WPF DataGrid is poorly designed in a few areas.
Meleak’s answer was very much on the right track. However, the problem is solvable and it can be solved without compromising your design or requiring repetitive Style setting. And perhaps more importantly, the problem is debuggable.
The following XAML works. I left old XAML commented out just to make the changes more visible. For a more in-depth look at the problem, please see the long answer.
DataGridResourceDictionary.xaml:
App.xaml:
MainWindow.xaml: