【问题标题】:WPF ListView Inactive Selection ColorWPF ListView 非活动选择颜色
【发布时间】:2010-09-27 18:37:18
【问题描述】:

我正在创建一个 WPF 应用程序,其中连续进行了多个 ListView 选择(类似于 iTunes 浏览器)。问题是默认的非活动选择颜色太浅了。 (见下文)

如何更改此颜色,使我的非活动列表视图看起来像这样? (见下文)

解决方案

使用Style 覆盖默认的 SystemColor,如下所示:

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

【问题讨论】:

    标签: wpf listview selection


    【解决方案1】:

    ListBox 模板使用称为ControlBrush 的系统颜色来设置非活动突出显示颜色。因此,您可以覆盖该颜色:

    <ListBox>
        <ListBox.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}">Red</SolidColorBrush>
        </ListBox.Resources>
    </ListBox>
    

    【讨论】:

    • 这样做有问题。它不允许您为应用程序设置皮肤,如果您通过更改 Windows 主题来更改系统颜色,它将恢复原状
    • 不允许您为应用设置皮肤?为何如此?只需查找颜色的资源,而不是硬编码为红色。我刚刚通过运行测试工具测试了更改主题,并且效果很好。请澄清。
    • 实际发生的是,您正在覆盖所有使用它的对象的样式键。
    • 它是一种资源,因此受制于资源查找的正常规则。米卡,你自己试试吧。将两个列表框放在一个窗口中——一个带有资源覆盖,一个没有。颜色更改仅影响具有资源覆盖的那个。
    • 对于 .NET 4.5,看起来他们更改了密钥 - 请参阅下面的 @user672951 答案。
    【解决方案2】:

    答案在某些情况下会解决问题,但并不理想,因为当控件被禁用/只读时它会中断,并且它还会覆盖配色方案,而不是利用它们。我的建议是在 ListBox 标记中添加以下内容:

    <ListBox....>
        <ListBox.Resources>
                <Style TargetType="ListBoxItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <Border Name="Border" Padding="2" SnapsToDevicePixels="true">
                                    <ContentPresenter />
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="true">
                                        <Setter TargetName="Border" Property="Background"
                                                Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
            </Style>
        </ListBox.Resources>
    </ListBox>
    

    这将在列表框项被选中时设置高亮背景颜色(无论控件状态如何)。

    我的回答基于已经给出的答案的帮助,以及以下博客:http://blogs.vbcity.com/xtab/archive/2009/06/29/9344.aspx

    【讨论】:

    • 这实现了 OP 的要求,但是请注意,这种样式会使所有文本变黑(在我的系统上,突出显示的文本通常是白色的,因为深蓝色上的黑色太难以阅读)。跨度>
    • @romkyns 只是创建一个常规触发器,当 IsSelected 为真时将前景设置为“HighlightTextBrushKey”。我将提交对答案的编辑,但它解决了您提到的问题。这是做 OP 想要的正确方法(字典方法会根据他们的主题对某些用户造成不必要的视觉副作用)......
    • 非常有用...我更喜欢这种方法,因为颜色不会覆盖任何其他颜色,并且在禁用控件时它可以工作,这是我的用例。谢谢!
    • 这适用于 .Net 4.6 上的 WPF。您不能为 ListBoxItem 创建通过 IsSelected 触发器直接覆盖 Background 的样式(这适用于许多属性,但不适用于背景)。我猜这是不同触发器的执行顺序的问题。您确实必须覆盖控件模板。
    【解决方案3】:

    更改SystemColors.ControlBrushKey 对我不起作用,我必须更改 SystemColors.InactiveSelectionHighlightBrushKey

    所以而不是:

    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Red" />
    

    我不得不使用:

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

    【讨论】:

    • 我也不得不改变这个值,ControlBrushKey 没有改变颜色。然而,我输入的颜色仍然在它上面应用了另一种颜色,所以我的蓝色看起来更紫色。你遇到过这种情况吗?
    • 我希望我能不止一次地支持这个答案,因为我已经多次尝试解决这个问题。我也在使用 .NET 4.5 并尝试了所有其他答案但均未成功。
    • 这是我在处理 .NET 4 项目之前使用的...我必须为我的 DataGridRow 实现类似于 .NET 4 的解决方案答案的样式,这样它才能更容易处理数据(很容易知道选择了什么)。
    • in .net 4.5 FrameworkCompatibilityPreferences.AreInactiveSelectionHighlightBrushKeysSupported 字段控制高亮使用哪种颜色。
    • SystemColors.ControlBrushKey 为我工作,谢谢。
    【解决方案4】:

    您必须覆盖 SystemColors 的某些属性。看看SystemColors Class (MSDN)。还有比 InactiveSelectionHighlightBrushKey 更多的属性,例如影响文本颜色的 InactiveSelectionHighlightTextBrushKey。

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="White"/>
            <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Yellow"/>
            <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="Blue"/>
            <Style TargetType="ListViewItem">
                <Setter Property="FontSize" Value="20" />
                <Setter Property="FontWeight" Value="Bold" />
                <Setter Property="Padding" Value="25,5" />
            </Style>
        </Window.Resources>
        <StackPanel Orientation="Horizontal">
            <ListView>
                <ListViewItem Content="Item" />
                <ListViewItem Content="Item" />
            </ListView>
            <ListView>
                <ListViewItem Content="Item" />
                <ListViewItem Content="Item" />
            </ListView>
        </StackPanel>
    </Window>
    

    【讨论】:

      【解决方案5】:

      对我来说,这成功了:

       <ListBox HorizontalContentAlignment="Stretch">
                      <ListBox.ItemTemplate>
                          <DataTemplate>
                              <Label  Margin="-5, -2,-5,-2" Content="{Binding Item}">
                                  <Label.Style>
                                      <Style TargetType="Label">
                                          <Style.Triggers>
                                              <MultiDataTrigger>
                                                  <MultiDataTrigger.Conditions>
                                                      <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}},Path=IsFocused}" Value="False"/>
                                                      <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True"/>
                                                  </MultiDataTrigger.Conditions>
                                                  <Setter Property="Background" Value="CornflowerBlue"/>
                                              </MultiDataTrigger>
                                              <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
                                                  <Setter Property="Foreground" Value="White"/>
                                              </DataTrigger>
                                              <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="False">
                                                  <Setter Property="Foreground" Value="Black"/>
                                              </DataTrigger>
                                          </Style.Triggers>
                                      </Style>
                                  </Label.Style>
                              </Label>
                          </DataTemplate>
                      </ListBox.ItemTemplate>
                  </ListBox>
      

      【讨论】:

        【解决方案6】:

        在较旧的 .NET 框架中,覆盖系统颜色不起作用。适用于 .NET Framework 4.0 的解决方案是 here

        <ListView>
        <ListView.Resources>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListViewItem}">
                        <Border x:Name="Bd"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}"
                                Padding="{TemplateBinding Padding}"
                                SnapsToDevicePixels="true">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive"
                                                Value="False" />
                                    <Condition Property="IsSelected"
                                                Value="True" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background"
                                        TargetName="Bd"
                                        Value="DarkOrange" />
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Selector.IsSelectionActive"
                                                Value="True" />
                                    <Condition Property="IsSelected"
                                                Value="True" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background"
                                        TargetName="Bd"
                                        Value="OrangeRed" />
                            </MultiTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        

        适用于 ListBox 和 ListView。

        【讨论】:

        • 虽然这可能是解决问题的宝贵提示,但一个好的答案也可以证明解决方案。请EDIT 提供示例代码来说明您的意思。或者,考虑将其写为评论
        【解决方案7】:

        基于this other answer,我使用以下方法使活动和非活动颜色相同,而无需对实际值进行硬编码:

        <ListBox.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" 
                             Color="{x:Static SystemColors.HighlightColor}"/>
            <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}"
                             Color="{x:Static SystemColors.HighlightTextColor}"/>
        </ListBox.Resources>
        

        为活动和非活动设置相同的颜色可能不是理想,但默认颜色太暗,很难分辨在非活动时选择了哪个项目;这是一个明显的改进。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-17
          • 1970-01-01
          • 2012-11-12
          • 2011-01-03
          • 2016-08-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多