WPF 4.0 DataGrid中的头部单元格和数据单元格的边框样式不一致。头部单元格的边框包括围绕头部文本的左竖直边框线和右竖直边框线。数据网格文本列数据行的样式只有右侧有竖直边框线。下面示例图像说明了这一点(请注意,网格线颜色已更改为#D0D0D0):
以下是放大后显示不一致的同一图像:
如何更改网格标题(可能通过模板或样式)以删除左边框,使得标题竖直边框线与数据边框线对齐?
![enter image description here](https://istack.dev59.com/8fAjH.webp)
![enter image description here](https://istack.dev59.com/cwrcv.webp)
为避免此问题,只需在DataGridColumnHeader样式中添加以下属性设置。
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="-1,-1,0,0" />
这个datagrid的问题在于边框绘制发生在左侧标题单元格边界内部。这会导致额外的线条,如上图所示。如果你还设置了datagrid的边框厚度,则问题也会出现在单元格顶部。
希望这些设置可以解决当厚度为'1'时的问题。对于其他厚度,你现在知道该如何调整了 :)
更新:添加了两个解决方案,都将产生如下所示的结果
DataGridHeaderBorder
设置 SeparatorVisibility="Collapsed"
Border
Xaml
<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>
DataGridColumnHeader
的分隔符是在DataGridHeaderBorder
的RenderTheme
方法中绘制的。这个类基本上是一个“全有或全无”的东西,因为更改其中任何属性都将禁用整个样式(没有边框、没有排序箭头等)。它也是密封的,所以我们不能从中派生。但是,我们可以复制整个类并使DataGridColumnHeader
使用该类。
绘制分隔符的部分如下:
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)));
}
从这里开始,我们可以只删除左分隔符,这样我们将得到一个分隔符宽度为1而不是2,但是当悬停、按下或排序列时,左侧的颜色会出现错误。为了克服这个问题,我们可以将左分隔符向左移动1个单位,并改变ZIndex,使悬停等操作的ZIndex高于普通着色。为了使其正常工作,我们还需要将DataGridColumnHeader
的ZIndex绑定到DataGridColumnBorder
的ZIndex。
我们可以像这样使用它
<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 太大了,无法发布,所以我在这里上传了它:MyDataGridHeaderBorder.cs
只需将HeaderStyle中的左边框厚度设置为0:
<Style x:Key="HeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="BorderThickness" Value="0,1,1,1"></Setter>
</Style>
DataGridCell
的两侧绘制分隔符来“加倍厚度”。也许这个问题可以帮到你:http://stackoverflow.com/questions/4737518/special-gridline-style-for-only-one-column。否则,你基本上需要重新创建整个DataGridColumnHeader
模板。 - Fredrik Hedblad