WPF DataGrid Exclude Row Details when Changing Selected Row Background
By Michael Detras
When we set the background color of a DataGridRow, the background color also gets applied to the row details template. This can be changed by modifying the default control template.
Let's say we have the following XAML for a WPF application window.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="150" Width="200">
<Window.Resources>
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<DataGrid AutoGenerateColumns="False" Name="dataGrid1">
<DataGrid.ItemsSource>
<Int32Collection>
<sys:Int32>1</sys:Int32>
</Int32Collection>
</DataGrid.ItemsSource>
<DataGrid.Columns>
<DataGridTextColumn Header="Column 1" Binding="{Binding}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Rectangle Fill="Black" Width="50" Height="50"/>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Window>
The following figure is a screenshot of the application, with the row details left
open.
You can see that the row details also have a red background. If we don't want the
background color be applied to the row details, we need to change the default
DataGridRow template, which is shown in the following.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<SelectiveScrollingGrid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<DataGridDetailsPresenter
SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=AreRowDetailsFrozen,
Converter={x:Static DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static
SelectiveScrollingOrientation.Vertical}}"
Grid.Column="1" Grid.Row="1"
Visibility="{TemplateBinding DetailsVisibility}"
/>
<DataGridRowHeader SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Grid.RowSpan="2"
Visibility="{Binding RelativeSource={RelativeSource
AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static
DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Row}}"/>
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
You can see that the root control of the template is a border, and its background
is bound to the templated control's background. We can remove this binding and
just add another border that will only contain the DataGrid cells, not the row
details. We will then bind the new border's background to the templated control's
background. Here is the updated template.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<SelectiveScrollingGrid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border
Background="{TemplateBinding Background}"
Grid.Column="1">
<DataGridCellsPresenter
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<DataGridDetailsPresenter
SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=AreRowDetailsFrozen,
Converter={x:Static DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static
SelectiveScrollingOrientation.Vertical}}"
Grid.Column="1" Grid.Row="1"
Visibility="{TemplateBinding DetailsVisibility}"
/>
<DataGridRowHeader
SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Grid.RowSpan="2"
Visibility="{Binding RelativeSource={RelativeSource
AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static
DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Row}}"/>
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Here is the updated figure.
Related FAQs
The WPF DataGrid is meant for showing a large amount of data. Due to this, it is confusing to see many rows without any alternating row colors.
Changing the background color of selected cells in a WPF DataGrid can easily be done by using styles in XAML.
WPF DataGrid Exclude Row Details when Changing Selected Row Background (3968 Views)