数据表格在未激活状态下的选中行颜色

81

当WPF DataGrid失去焦点时,我该如何样式化它以更改选择行的颜色?

12个回答

141

在寻找了很长时间之后,我发现了一个出乎意料的简单方法来完成这个任务,它比之前发布的Got/LostFocus方法更加干净:

<DataGrid.Resources>
    <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="DarkGray"/>
</DataGrid.Resources>

这只是将非活动背景颜色设置为DarkGray,使活动背景颜色保持默认值,但您当然也可以使用SystemColors.HighlightBrushKey更改活动背景颜色。

非活动选择的前景资源键是SystemColors.InactiveSelectionHighlightTextBrushKey。


1
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="{DynamicResource {x:Static SystemColors.HighlightColorKey}}" /> - 不会更正文本颜色 - jtimperley
4
InactiveSelectionHighlightBrushKey 只能在 .NET Framework 4.5 上工作,而在 .NET Framework 4.0 上会引发异常。我在这里写了更多相关内容:https://dev59.com/imYr5IYBdhLWcg3wRoOW#13827971 - Mikhail Shcherbakov
52
在.NET 4.5中,我使用以下代码: <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="{x:Static SystemColors.HighlightColor}"/> <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="{x:Static SystemColors.HighlightTextColor}"/> - Heiner
1
为什么我们需要为SystemColor键指定一个新值,而不像通常那样给Background设置另一种颜色?这是因为DataGrid在代码中覆盖了Background颜色吗? 还是因为我们的值来自静态上下文的原因? - eran otzap
5
InactiveSelectionHighlightBrushKey在.NET 4.0中不可用 :( - BigSandwich

29

完整的解决方案适用于4.0版本。请注意,这是在CellStyle上的。

<DataGrid.CellStyle>
    <!--Override Highlighting so that its easy to see what is selected even when the control is not focused-->
    <Style TargetType="{x:Type DataGridCell}">
        <Style.Triggers>
            <Trigger  Property="IsSelected" Value="true">
                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
                <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
            </Trigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True" />
                    <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=IsKeyboardFocusWithin}" Value="False" />
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.Setters>
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
                    <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                </MultiDataTrigger.Setters>
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>
</DataGrid.CellStyle>

10

按照以下方式操作:

<DataGrid ...>
    <DataGrid.Resources> 
        <Style TargetType="DataGridRow"> 
            <Style.Resources> 
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>                                  
            </Style.Resources> 
        </Style> 
   </DataGrid.Resources> 
...

谢谢你的回答!它改变了选择颜色。但是对于活动焦点情况也是如此。所以行始终是红色的,无论它是活动的还是非活动的。而我需要另一种行为:当DataGrid有焦点时,选中的行是蓝色的,当DataGrid没有焦点时,选中的行是红色的。 - white.zaz
@HCL为什么我们需要为SystemColor键指定一个新值,而不像通常那样给Background设置另一种颜色?这是因为DataGrid在代码中覆盖了背景颜色吗? 还是因为我们的值来自静态上下文的原因? - eran otzap

8

这些答案都没有完全满足我的要求。Steve Streeting 给出的最佳答案会改变我不想更改的数据网格的其他部分,而其他答案虽然正确地针对了行,但没有提供 非活动 颜色的更改。所以,这里是他们答案的混合体,只在行上更改 非活动 颜色,而不影响网格的其他位置。

<DataGrid.Resources>
    <Style TargetType="DataGridRow">
        <Style.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="DarkGray"/>
        </Style.Resources>
    </Style>
</DataGrid.Resources>

7

迟来的答复:

这在.Net 4.0中可行,而且您不必硬编码颜色:

<Style TargetType="DataGridRow">
    <Style.Resources>
         <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="{x:Static SystemColors.HighlightColor}" />
         <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="{x:Static SystemColors.HighlightTextColor}"/>
    </Style.Resources>
</Style>

4
您应该在DataGrid中定义"DataGrid.CellStyle"部分,如下所示:
    <DataGrid>
        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="LightBlue"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>

但是为什么它会这样工作呢?为什么SelectedRow触发器不够? - Dodikaedr

4
对于 .Net Framework 4.0(或者如果你不想使用 InactiveSelection... 刷子键): 创建一个 DataGridRow 样式/控件模板,然后添加以下触发器:
<ControlTemplate.Triggers>
    <Trigger  Property="IsSelected" Value="true">
        <Setter Property="Background" Value="{DynamicResource SelectionBrush}" />
    </Trigger>
    <MultiDataTrigger>
        <MultiDataTrigger.Conditions>
            <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True" />
            <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=IsKeyboardFocusWithin}" Value="False" />
        </MultiDataTrigger.Conditions>
        <MultiDataTrigger.Setters>
            <Setter Property="Background" Value="{DynamicResource InactiveSelectionBrush}" />
        </MultiDataTrigger.Setters>
    </MultiDataTrigger>
</ControlTemplate.Triggers>

你可能需要为 DataGrid.CellStyle 而不是行执行此操作。我仍然不清楚每个样式何时被使用。 - BigSandwich
2
好的,这段代码放在哪里?是在<DataGrid.RowStyle>中还是在<DataGrid>中?一个完整的、可用的答案会很有用。 - Stealth Rabbi

4
我将此添加到我的ResourceDictionary中,以便它适用于程序中的所有数据网格。
<Style TargetType="DataGrid">
    <Style.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="LightGray"/>
    </Style.Resources>        
</Style>

3

独立解决问题。

在DataGrid的资源中添加一个画刷,可以从代码后台更改其“Color”属性,并将HighlightBrushKey引用到它:

<DataGrid.Resources>
    <SolidColorBrush x:Key="SelectionColorKey" Color="DarkGray"/>
    <Style TargetType="DataGridRow">
        <Style.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{Binding Source={StaticResource SelectionColorKey}, Path=Color}"/>
        </Style.Resources>
    </Style>
</DataGrid.Resources>

然后添加DataGrids事件处理程序以手动更改颜色:

private void DataGrid1_LostFocus(object sender, RoutedEventArgs e)
{
    ((SolidColorBrush)DataGrid1.Resources["SelectionColorKey"]).Color = Colors.DarkGray;
}

private void DataGrid1_GotFocus(object sender, RoutedEventArgs e)
{
    ((SolidColorBrush)DataGrid1.Resources["SelectionColorKey"]).Color = SystemColors.HighlightColor;
}

private void DataGrid1_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    ((SolidColorBrush)DataGrid1.Resources["SelectionColorKey"]).Color = Colors.DarkGray;
}

3

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