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

时间:2011-03-06 21:46:26

标签: wpf wpf-controls wpfdatagrid

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

enter image description here

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

enter image description here

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

3 个答案:

答案 0 :(得分:19)

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

<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="-1,-1,0,0" />

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

希望此设置将解决厚度为“1”时的问题。对于其他厚度,您现在知道需要调整的内容:)

答案 1 :(得分:5)

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

等结果

enter image description here

解决方案1 ​​

  • SeparatorVisibility="Collapsed"
  • 设置DataGridHeaderBorder
  • 将左右分隔符添加为Border s
  • 在触发器中处理悬停按下排序
  • 添加对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>

解决方案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)));
            }

从这里我们可以删除左侧分隔符,我们会得到一个分隔符宽度为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

答案 2 :(得分:-1)

只需将HeaderStyle中的左边框thichkness设置为0:

<Style x:Key="HeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="BorderThickness" Value="0,1,1,1"></Setter>
</Style>