如何在应用列标题背景后添加排序箭头

28

在对列标题应用背景颜色后,排序箭头不见了。如何将其添加回来?

3个回答

47

我认为你需要重新设计DataGridColumnHeader的模板,并从那里添加它。这里有一个例子。你需要添加对PresentationFramework.Aero的引用。

xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"

<DataGrid ...>
    <DataGrid.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 TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="Background" Value="Blue"/>
            <Setter Property="BorderBrush" Value="Red"/>
            <Setter Property="BorderThickness" Value="1,1,1,1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                        <Grid>
                            <Themes:DataGridHeaderBorder 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}">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <ContentPresenter Grid.Column="0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                    <Path x:Name="SortArrow"
                                            Grid.Column="1"
                                            HorizontalAlignment="Right" VerticalAlignment="Center"                                           
                                            Width="8" Height="6" Margin="2,0,5,0"
                                            Stretch="Fill" Opacity="0.5" Fill="White"
                                            RenderTransformOrigin="0.5,0.4"
                                            Visibility="Collapsed"
                                            Data="M0,0 L1,0 0.5,1 z" />
                                </Grid>
                            </Themes:DataGridHeaderBorder>
                            <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/>
                            <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="SortDirection" Value="Ascending">
                                <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                                <Setter TargetName="SortArrow" Property="RenderTransform">
                                    <Setter.Value>
                                        <RotateTransform Angle="180" />
                                    </Setter.Value>
                                </Setter>
                            </Trigger>
                            <Trigger Property="SortDirection" Value="Descending">
                                <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.Resources>
</DataGrid>

8
为什么这么复杂?有没有简单的方法? - user496949
@user496949:恐怕是这样。排序箭头应该放在模板中(与标题等一起),所以要想把它们拿回来,我们就必须重新设计整个模板。我从来没有见过任何绕过这个问题的方法。 - Fredrik Hedblad
是的,这是唯一的方法。 - dex3703
嗨@FredrikHedblad,有没有办法以编程方式触发箭头?您可以参考这里的问题https://stackoverflow.com/questions/50331237/wpf-mvvm-trigger-datagrid-sort-directions-arrow-programmatically - Nerdynosaur
天才,谢谢;我希望微软能够像Web CSS一样为我们提供简单的方式,只需几行简短的代码就可以轻松实现。 - RAMM-HDR

8
这是一篇关于DataGridColumnHeader模板过程的博客文章,作者非常详细地解释了该过程并提供了结果的可视化效果。点击Terry Hutt的博客文章

这里展示了默认列标题。单击列标题以重新排序列。您还可以通过拖动标题来重新排序列,并通过拖动标题两端的隐藏缩略图来调整它们的大小。标题本身显然是一个带有可选排序指示器的按钮位于文本上方。看起来相当糟糕。
让我们尝试更改标题的背景色,使其不再像按钮那样明显。DataGrid具有ColumnHeaderStyle属性。我们可以使用它,但为简单起见,让我们通过将此内容添加到XAML中来创建我们的列标题的默认样式...
<Window.Resources>
    <Style TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="Background" Value="LightGray"/>
    </Style>
</Window.Resources>

如果您使用新样式运行项目,则标题看起来更漂亮。但是等等,我们的排序指示器去哪了?原来,DataGridColumnHeader被有意地设计成如果更改背景颜色,则隐藏排序指示器。有时我真的不明白微软是如何生存下来的。为什么要设计这样一个丑陋的控件,然后在开发人员试图修复它时破坏其他关键功能。
我们必须重新模板化DataGridColumnHeader。当我们在那里时,让我们玩一些乐趣!这就是我们要做的...
更改背景颜色 使用边框创建下划线 当鼠标悬停在标题上方时,更改边框的颜色 将排序指示器移到标题文本的侧面而不是上面 使列宽拇指不可见,但在光标悬停在它们上面时更改光标
步骤1-加强样式,使其看起来像这样...
<Style TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="MinWidth" Value="0"/>
    <Setter Property="MinHeight" Value="0"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="Background" Value="LightGray"/>
    <Setter Property="Cursor" Value="Hand"/>
</Style>

第二步 - 编写控件模板,定义标题区域、排序指示器、边框和拇指。网格控件负责标题的布局,内容区域位于左侧,排序指示器位于右侧。请注意,排序指示器是使用路径定义的。两个矩形为列标题产生可见的左右边缘。必须定义Thumb并允许用户调整列大小。我们稍后将定义ThumbStyle。请注意Border的名称。我们需要这样做,以便在第三步中使用触发器进行更改。请在闭合Style标记之前添加此内容。

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Border x:Name="BackgroundBorder" BorderThickness="0,0,0,2"
                        Background="LightGray"
                        BorderBrush="Black"
                        Grid.ColumnSpan="2"/>
                <ContentPresenter Margin="6,3,6,3" VerticalAlignment="Center"/>
                <Path x:Name="SortArrow" Visibility="Collapsed" Data="M 0,0 L 1,0 0.5,1 z" Stretch="Fill"
                     Grid.Column="1" Width="8" Height="6" Fill="Black" Margin="0,0,8,0"
                      VerticalAlignment="Center" RenderTransformOrigin="0.5, 0.4"/>
                <Rectangle Width="1" Fill="#EEEEEE" HorizontalAlignment="Right" Grid.ColumnSpan="2"/>
                <Rectangle Width="1" Margin="0,0,1,0" Fill="#DDDDDD" HorizontalAlignment="Right" Grid.ColumnSpan="2"/>
                <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ThumbStyle}"/>
                <Thumb x:Name="PART_RightHeaderGripper" Grid.Column="1" HorizontalAlignment="Right" Style="{StaticResource ThumbStyle}"/>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>

步骤三- 当鼠标移动到列标题上时,添加触发器以更改边框的颜色。在Grid结束标记后添加以下触发器。

<ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        <Setter TargetName="BackgroundBorder" Property="Background" Value="LightGray"/>
        <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="Orange"/>
    </Trigger>
</ControlTemplate.Triggers>

步骤4 - 添加触发器,以在对列进行排序时显示和/或旋转排序指示器。

<Trigger Property="SortDirection" Value="Ascending">
    <Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
    <Setter TargetName="SortArrow" Property="RenderTransform">
        <Setter.Value>
            <RotateTransform Angle="180"/>
        </Setter.Value>
    </Setter>
</Trigger>
<Trigger Property="SortDirection" Value="Descending">
    <Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
</Trigger>

步骤五 - 隐藏第0列的LeftHeaderGripper - 我们不需要它。

<Trigger Property="DisplayIndex" Value="0">
    <Setter TargetName="PART_LeftHeaderGripper" Property="Visibility" Value="Collapsed"/>
</Trigger>

如承诺,这里是ThumbStyle定义。请将其插入到DataGridColumnHeader样式之前。我使用了一个光标为SizeWE的不可见矩形。如果您选择,您可以对其进行着色或完全使用其他内容。

<Style TargetType="{x:Type Thumb}" x:Key="ThumbStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Rectangle Width="1" Stroke="Transparent" Cursor="SizeWE"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

更新:风格条目已合并在一起

<FontFamily x:Key="Corp_FontFamily">Segoe UI</FontFamily>
<clr:Double x:Key="Corp_FontSize">13</clr:Double>
<Style TargetType="{x:Type Control}" x:Key="baseStyle">
    <Setter Property="FontFamily" Value="{StaticResource Corp_FontFamily}" />
    <Setter Property="FontSize" Value="{StaticResource Corp_FontSize}" />
</Style>

<Color x:Key="CorpBlue_T1S1" A="255" R="172" G="180" B="196"/>
<SolidColorBrush x:Key="Brush_CorpBlue_T1S1" Color="{StaticResource CorpBlue_T1S1}"/>

<Color x:Key="CLR_Green" A="255" R="220" G="239" B="202"/>
<SolidColorBrush x:Key="YourCompany_HeaderColumnDefaultBackground" Color="{StaticResource CLR_Green}"/>

<Style TargetType="DataGridColumnHeader" x:Key="DG_Hdr_Base" BasedOn="{StaticResource baseStyle}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="MinWidth" Value="0"/>
    <Setter Property="MinHeight" Value="0"/>
    <Setter Property="Background" Value="{StaticResource YourCompany_HeaderColumnDefaultBackground}"/>
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="Padding" Value="5"/>
    <Setter Property="BorderThickness" Value="0 0 1 0"/>
    <Setter Property="BorderBrush" Value="DarkGray"/>
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="TextBlock.TextAlignment" Value="Center" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="DataGridColumnHeader">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Border x:Name="BackgroundBorder" BorderThickness="0,0,0,2"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            Grid.ColumnSpan="2"/>
                    <ContentPresenter Margin="5" VerticalAlignment="Center" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                    <Path x:Name="SortArrow" Visibility="Collapsed" Data="M 0,0 L 1,0 0.5,1 z" Stretch="Fill"
                         Grid.Column="1" Width="8" Height="6" Fill="Black" Margin="0,0,8,0"
                          VerticalAlignment="Center" RenderTransformOrigin="0.5, 0.4"/>
                    <Rectangle Width="1" Fill="DarkGray" HorizontalAlignment="Right" Grid.ColumnSpan="2"/>
                    <Rectangle Width="1" Margin="0,0,1,0" Fill="DarkGray" HorizontalAlignment="Right" Grid.ColumnSpan="2"/>
                    <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ThumbStyle}"/>
                    <Thumb x:Name="PART_RightHeaderGripper" Grid.Column="1" HorizontalAlignment="Right" Style="{StaticResource ThumbStyle}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="BackgroundBorder" Property="Background" Value="{StaticResource Brush_CorpBlue_T1S1}"/>
                        <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="{StaticResource ControlHighlightBorderBrush}"/>
                    </Trigger>
                    <Trigger Property="SortDirection" Value="Ascending">
                        <Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
                        <Setter TargetName="SortArrow" Property="RenderTransform">
                            <Setter.Value>
                                <RotateTransform Angle="180"/>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="SortDirection" Value="Descending">
                        <Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
                    </Trigger>
                    <Trigger Property="DisplayIndex" Value="0">
                        <Setter TargetName="PART_LeftHeaderGripper" Property="Visibility" Value="Collapsed"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Display result


1
非常棒的例子。建议添加最后一个显示,以说明所有元素是如何一起定义的,对于那些经验较少的人来说更容易理解。 - str8ball
1
感谢您的反馈@str8ball。已经添加了样式元素的整合。 - Galactic
表格的标题文本是否可以像上面的示例一样左对齐,也可以居中对齐? - TsunamiCoder

3

可能有更好的解决方案,但我只是根据排序方向将字符▴或▾附加到列标题上。

最初的回答:

There may be better solutions, but I simply appended the character ▴ or ▾ to the column header based on sort direction.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接