删除WPF DataGrid标题列的左边框网格线以匹配数据网格线

Mic*_*eyn 9 wpf wpf-controls wpfdatagrid

WPF 4.0 DataGrid中标题单元格和数据单元格的边框样式不一致.标题单元格的边框包含左侧垂直边框线和标题文本周围的右侧垂直边框线.数据网格文本列数据行的样式使得只有右侧具有垂直边界线.以下示例图像说明了这一点(请注意,网格线颜色已更改为#D0D0D0):

在此输入图像描述

以下是放大显示不一致性的相同图像:

在此输入图像描述

如何更改网格标题(可能通过模板或样式)以删除左边框,以便标题垂直边框线与数据边框线对齐?

小智 19

要避免这种情况,只需在DataGridColumnHeader样式中添加以下属性设置即可.

<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="-1,-1,0,0" />
Run Code Online (Sandbox Code Playgroud)

此数据网格中的问题是边框绘制发生在左侧的标题单元格边界内.这导致了额外的衬里,如上图所示.如果你还设置了datagrid的broderthickness,那么问题也将出现在单元格的顶部.

希望此设置将解决厚度为"1"时的问题.对于其他厚度你现在知道你需要调整:)


Fre*_*lad 5

更新:添加了两个解决方案,两者都会产生结果

在此输入图像描述

解决方案1

  • 设置SeparatorVisibility="Collapsed"DataGridHeaderBorder
  • 添加左右分隔符为Borders
  • 在触发器中处理悬停,按下排序
  • 添加对PresentationFramework.Aero的引用

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>
Run Code Online (Sandbox Code Playgroud)

解决方案2

分隔符DataGridColumnHeader是在RenderTheme方法中绘制的DataGridHeaderBorder.这个类几乎是"全有或全无"的交易,因为更改其中的任何属性将禁用整个样式(没有边框,没有排序箭头等).它也是密封的,所以我们无法从中得到它.然而,我们可以复制整个类,并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)));
            }
Run Code Online (Sandbox Code Playgroud)

从这里我们可以删除左分隔符,我们将得到1的分隔符宽度而不是2但是当悬停,按下排序列时,我们将得到左侧的错误着色.为了克服这个问题,我们可以将左侧分隔符向左移动1并更改ZIndex,因此悬停等比正常着色获得更高的ZIndex.为此,我们还需要将ZIndex绑定DataGridColumnHeader到ZIndex DataGridColumnBorder.

我们可以像这样使用它

<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>
Run Code Online (Sandbox Code Playgroud)

MyDataGridHeaderBorder很大,所以我上传了它:MyDataGridHeaderBorder.cs

  • 哇,我没有意识到改变某些线条的厚度会很复杂. (3认同)