The border styles for header cells and data cells in a WPF 4.0 DataGrid are inconsistent.. Header cells have a border that includes a left vertical border line and a right vertical border line around the header text. Data grid text column data lines are styled such that only the right side has a vertical border line. The following sample image illustrates this (note that the grid line color has been changed to #D0D0D0):
Here is the same image zoomed in to show the inconsistency:
How do you change the grid headers (perhaps via a templates or styles) to remove the left border, so that the header vertical border lines line up with the data border lines?
To avoid this just add below property setting in DataGridColumnHeader style.
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="-1,-1,0,0" />
The issue in this datagrid is the border drawing is happening inside header cell boundry on left side. This is causing the additional lining as shown in the picture above. If you also set datagrid's broderthickness then issue will appear on for top side of the cell also.
Hope this settings will solve problem when thickness is '1'. For other thicknesses you know now what you have to adjust :)
Update: Added two solutions, both will produce result like
SeparatorVisibility="Collapsed"
for DataGridHeaderBorder
Border
sXaml
<DataGrid ...>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<Style.Resources>
<Style x:Key="ColumnHeaderGripperStyle" 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 Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="normalBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFF2F2F2" Offset="0" />
<GradientStop Color="#FFEFEFEF" Offset="0.4" />
<GradientStop Color="#FFE7E8EA" Offset="0.4" />
<GradientStop Color="#FFDEDFE1" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="pressedBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FF7A9EB1" Offset="0" />
<GradientStop Color="#FF7A9EB1" Offset="0.4" />
<GradientStop Color="#FF5091AF" Offset="0.4" />
<GradientStop Color="#FF4D8DAD" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="hoveredBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FF88CBEB" Offset="0" />
<GradientStop Color="#FF88CBEB" Offset="0.4" />
<GradientStop Color="#FF69BBE3" Offset="0.4" />
<GradientStop Color="#FF69BBE3" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="sortedBrush" Color="#FF96D9F9"/>
</Style.Resources>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border x:Name="separatorLeft" Grid.Column="0" Width="1" HorizontalAlignment="Left"
Background="{StaticResource normalBrush}">
<Border.RenderTransform>
<TranslateTransform X="-1"/>
</Border.RenderTransform>
</Border>
<Microsoft_Windows_Themes:DataGridHeaderBorder x:Name="headerBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" IsClickable="{TemplateBinding CanUserSort}" IsPressed="{TemplateBinding IsPressed}" IsHovered="{TemplateBinding IsMouseOver}" Padding="{TemplateBinding Padding}" SortDirection="{TemplateBinding SortDirection}" SeparatorBrush="{TemplateBinding SeparatorBrush}"
SeparatorVisibility="Collapsed">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Microsoft_Windows_Themes:DataGridHeaderBorder>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/>
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/>
<Border x:Name="separatorRight" Grid.Column="1" Width="1" Background="{StaticResource normalBrush}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="separatorRight" Property="Background" Value="{StaticResource pressedBrush}"/>
<Setter TargetName="separatorLeft" Property="Background" Value="{StaticResource pressedBrush}"/>
<Setter Property="Panel.ZIndex" Value="2"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="separatorRight" Property="Background" Value="{StaticResource hoveredBrush}"/>
<Setter TargetName="separatorLeft" Property="Background" Value="{StaticResource hoveredBrush}"/>
<Setter Property="Panel.ZIndex" Value="2"/>
</Trigger>
<Trigger Property="SortDirection" Value="Ascending">
<Setter TargetName="separatorRight" Property="Background" Value="{StaticResource sortedBrush}"/>
<Setter TargetName="separatorLeft" Property="Background" Value="{StaticResource sortedBrush}"/>
<Setter Property="Panel.ZIndex" Value="2"/>
</Trigger>
<Trigger Property="SortDirection" Value="Descending">
<Setter TargetName="separatorRight" Property="Background" Value="{StaticResource sortedBrush}"/>
<Setter TargetName="separatorLeft" Property="Background" Value="{StaticResource sortedBrush}"/>
<Setter Property="Panel.ZIndex" Value="2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
<!--...-->
</DataGrid>
The Separators for DataGridColumnHeader
is drawn in the RenderTheme
method in DataGridHeaderBorder
. This class is pretty much an "all or nothing" deal since changing any property in it will disable the entire style (no border, no sort-arrows etc.). It is also sealed so we can't derive from it. We can however copy the entire class and make the DataGridColumnHeader
s use that class instead.
The part that draws the separators looks like this
private void RenderTheme(DrawingContext dc)
{
// ...
if (this.SeparatorVisibility == Visibility.Visible)
{
// ...
// Draw Left Separator
dc.DrawRectangle(separatorBrush, null, new Rect(0, 0.0, 1.0, Max0(renderSize.Height - 0.95)));
// Draw Right Separator
dc.DrawRectangle(separatorBrush, null, new Rect(renderSize.Width - 1.0, 0.0, 1.0, Max0(renderSize.Height - 0.95)));
}
From here we could just remove the Left Separator and we would get a Separator Width of 1 instead of 2 but then we would get the wrong coloring for the left side when Hovering, Pressing or Sorting a column. To overcome this we can move the Left Separator by 1 to the Left and change the ZIndex so Hovering etc. gets higher ZIndex than normal coloring. For this to work we also need to bind ZIndex of DataGridColumnHeader
to ZIndex of DataGridColumnBorder
.
We can use it like this
<DataGrid ...>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Resources>
<Style x:Key="ColumnHeaderGripperStyle" 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 Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<local:MyDataGridHeaderBorder Panel.ZIndex="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridColumnHeader}}, Path=(Panel.ZIndex), Mode=TwoWay}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" IsClickable="{TemplateBinding CanUserSort}" IsPressed="{TemplateBinding IsPressed}" IsHovered="{TemplateBinding IsMouseOver}" Padding="{TemplateBinding Padding}" SortDirection="{TemplateBinding SortDirection}" SeparatorBrush="{TemplateBinding SeparatorBrush}" SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</local:MyDataGridHeaderBorder>
<Thumb x:Name="PART_LeftHeaderGripper" Panel.ZIndex="4" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/>
<Thumb x:Name="PART_RightHeaderGripper" Panel.ZIndex="4" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
<!--...-->
</DataGrid>
MyDataGridHeaderBorder was to big to post so I uploaded it here: MyDataGridHeaderBorder.cs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With