更改 WPF ListBox 中 SelectedItem 的背景 [英] Changing The Background Of SelectedItem In WPF ListBox

查看:27
本文介绍了更改 WPF ListBox 中 SelectedItem 的背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题已经被问到&在这里回答了大约十几次,但给出的答案似乎都不起作用.问题:在 WPF 列表框中,如何更改(所选项目和/或鼠标悬停"项目的)突出显示颜色?

这不起作用(根据

选择编辑副本..."菜单项.

这将向您的文件添加新资源,如下所示:

<SolidColorBrush x:Key=Item.MouseOver.Border"颜色=#a826A0Da"/><SolidColorBrush x:Key=Item.SelectedInactive.Background"颜色=#3DDADADA"/><SolidColorBrush x:Key=Item.SelectedInactive.Border"颜色=#FFDADADA"/><SolidColorBrush x:Key=Item.SelectedActive.Background"颜色=#3D26A0DA"/><SolidColorBrush x:Key=Item.SelectedActive.Border"颜色=#FF26A0DA"/><Style x:Key="ListBoxItemStyle1";TargetType={x:Type ListBoxItem}"><Setter 属性 =SnapsToDevicePixels"值=真"/><Setter 属性 =填充"值=4,1"/><Setter Property="Horizo​​ntalContentAlignment";值={Binding Horizo​​ntalContentAlignment,RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/><Setter Property="VerticalContentAlignment";值={Binding VerticalContentAlignment,RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/><Setter 属性 =背景"值=透明"/><Setter 属性 =BorderBrush"值=透明"/><Setter 属性 =BorderThickness";值=1"/><Setter 属性 =FocusVisualStyle"值={StaticResource FocusVisual}"/><Setter 属性 =模板"><Setter.Value><ControlTemplate TargetType="{x:Type ListBoxItem}"><Border x:Name=Bd";BorderBrush="{TemplateBinding BorderBrush}";BorderThickness="{TemplateBinding BorderThickness}";背景={模板绑定背景}";Padding="{TemplateBinding Padding}";SnapsToDevicePixels=真"><ContentPresenter Horizo​​ntalAlignment="{TemplateBinding Horizo​​ntalContentAlignment}";SnapsToDevicePixels={TemplateBinding SnapsToDevicePixels}"VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/></边框><ControlTemplate.Triggers><多重触发><MultiTrigger.Conditions><条件属性=IsMouseOver"值=真"/></MultiTrigger.Conditions><Setter 属性 =背景"目标名称=Bd"值={StaticResource Item.MouseOver.Background}"/><Setter 属性 =BorderBrush"目标名称=Bd"值={StaticResource Item.MouseOver.Border}"/></多触发器><多重触发><MultiTrigger.Conditions><条件属性=Selector.IsSelectionActive"值=假"/><条件属性=IsSelected"值=真"/></MultiTrigger.Conditions><Setter 属性 =背景"目标名称=Bd"值={StaticResource Item.SelectedInactive.Background}"/><Setter 属性 =BorderBrush"目标名称=Bd"值={StaticResource Item.SelectedInactive.Border}"/></多触发器><多重触发><MultiTrigger.Conditions><条件属性=Selector.IsSelectionActive"值=真"/><条件属性=IsSelected"值=真"/></MultiTrigger.Conditions><Setter 属性 =背景"目标名称=Bd"值={StaticResource Item.SelectedActive.Background}"/><Setter 属性 =BorderBrush"目标名称=Bd"值={StaticResource Item.SelectedActive.Border}"/></多触发器><触发器属性=IsEnabled"值=假"><Setter Property="TextElement.Foreground";目标名称=Bd"值={DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/></触发器></ControlTemplate.Triggers></控制模板></Setter.Value></Setter></风格>

它还将更新 XAML 中的 ListBox 以引用项目容器模板的该样式.此时,您可以根据自己的喜好编辑资源.例如,更改 "Item.SelectedActive.Background" 键的画笔:

鉴于 WPF 文档确实讨论了资源层次结构以及如何通过键找到资源,似乎应该可以在不完全覆盖这样的项目容器样式的情况下使其工作.但目前我看不出有什么办法.

就其价值而言,上述内容基本上是在使用 C# 更改 WPF 列表框 SelectedItem 文本颜色和高亮/背景颜色中提出的

a>,减去该问题中发现的所有额外细节.从某种意义上说,这个问题可以被认为是那个的重复.

如果您经常遇到这些问题并且想要一个不那么混乱的解决方案,那么您可能会发现其他一些问题.特别是,您可以使用标记扩展来自定义样式的处理方式,允许您在编译时合并或以其他方式操作资源字典.这是一种复杂得多的方法,但如果这在您的项目中经常出现,则可能是值得的.见例如:XAML 组合样式如何在 WPF 中应用多种样式您的问题确实不是其中任何一个的重复,但无论如何基本技术都可以应用于您的情况.

This question has been asked & answered on here about a dozen times, but none of the given answers seem to work. The question: In a WPF ListBox, how do you change the highlight color (of the selected item, and/or the 'mouseover' item)?

This does not work (per here) - the highlight remains as default:

<StackPanel>
    <StackPanel.Resources>
        <Style x:Key="ListBoxSelectedItemsStyle" TargetType="{x:Type ListBoxItem}">
            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Black" />
            </Style.Resources>
        </Style>
    </StackPanel.Resources>
    <ListBox ItemContainerStyle="{StaticResource ListBoxSelectedItemsStyle}">
        <ListBoxItem>Item1</ListBoxItem>
        <ListBoxItem>Item2</ListBoxItem>
        <ListBoxItem>Item3</ListBoxItem>
    </ListBox>
</StackPanel>

This also does not work (slight variation, per here):

<StackPanel>
    <ListBox>
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Style.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Yellow"/>
                </Style.Resources>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBoxItem>Item1</ListBoxItem>
        <ListBoxItem>Item2</ListBoxItem>
        <ListBoxItem>Item3</ListBoxItem>
    </ListBox>
</StackPanel>

This also does not work (per here):

<StackPanel>
    <ListBox>
        <ListBox.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Black"/>
            <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Black"/>
            <Style TargetType="{x:Type ListBoxItem}">
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="Black"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListBox.Resources>
        <ListBoxItem>Item1</ListBoxItem>
        <ListBoxItem>Item2</ListBoxItem>
        <ListBoxItem>Item3</ListBoxItem>
    </ListBox>
</StackPanel>

Many many answers include some variation of this (i.e. here, etc) - but no matter which I use, nothing changes. The highlight remains unaffected.

解决方案

All three of the versions you tried amount to basically the same thing: they provide a new resource, using the same key that is used by the default ListBoxItem control template. In theory, by providing a new resource item with the same key, when it comes time for the framework to look for the appropriate resource, it will traverse the loaded resource dictionaries, find yours first, and use that instead of the original one used by default.

But it seems that there are a couple of problems:

  • First, the key being used has changed since those references were provided. When I look at the current ListBoxItem style, it uses regular strings as keys, not these properties in the SystemColors class. The current key name is "Item.SelectedActive.Background" for setting the background when the item is selected and has focus.
  • Secondly though, even when using the new key, I was unable to get the resource item to be found and used. The original default brush is still being used, in spite of the theory being sound.

There is probably some way to still get it to work. But figuring that out would take time, stepping through the code in the debugger and watching to see what WPF is doing when the control is initialized and when the trigger is triggered. Such an investigation would probably shed light on how WPF is looking up the resource, and how one might manage to cause your own resource with the same key to be found instead.

But at the moment, I don't have time to do all that. And I do know how to make it work via brute force. One of the biggest hammers in the XAML toolbox is the "Edit Template" command in the XAML Designer. For this particular purpose, you want to create a copy of the ListBoxItem template so you can use an edited version of that. Right-click on the ListBox in Design mode in the XAML editor and go to this menu:

Choose the "Edit a Copy…" menu item.

That will add new resources to your file that look like this:

<SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/>
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
  <Setter Property="SnapsToDevicePixels" Value="True"/>
  <Setter Property="Padding" Value="4,1"/>
  <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="Background" Value="Transparent"/>
  <Setter Property="BorderBrush" Value="Transparent"/>
  <Setter Property="BorderThickness" Value="1"/>
  <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ListBoxItem}">
        <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="IsMouseOver" Value="True"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
          </MultiTrigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="Selector.IsSelectionActive" Value="False"/>
              <Condition Property="IsSelected" Value="True"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
          </MultiTrigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="Selector.IsSelectionActive" Value="True"/>
              <Condition Property="IsSelected" Value="True"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
          </MultiTrigger>
          <Trigger Property="IsEnabled" Value="False">
            <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

It will also update the ListBox in the XAML to reference that style for the item container template. At this point, you can edit the resources to your heart's content. For example, change the brush for the "Item.SelectedActive.Background" key:

<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="Black"/>

Given that the WPF documentation does discuss the resource hierarchy and how resources are found by key, it does seem like it should be possible to get this to work without completely overriding the item container style like this. But I don't see a way how at the moment.

For what it's worth, the above is basically what is being proposed in Changing WPF Listbox SelectedItem text color and highlight/background Color using C#, minus all the extra details found in that question. In a sense, this question could be considered a duplicate of that.

There are a couple of other questions that you might find relevant, if this is something you run into a lot and want a less messy solution. In particular, you can use markup extensions to customize how styles are handled, allowing you to merge or otherwise manipulate the resource dictionaries as they are handled at compile time. This is a lot more complicated approach, but might be worth it if this comes up a lot in your projects. See e.g.: XAML Combine Styles How to apply multiple styles in WPF Your question really is not a duplicate of either of those, but the basic technique could be applied in your situation anyway.

这篇关于更改 WPF ListBox 中 SelectedItem 的背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆