当ListBoxItem没有焦点时,如何覆盖背景颜色(.NET 4.5)

11
根据这个,覆盖ControlBrushKey资源应该可以改变ListBox选定项的背景颜色,当它没有焦点时。我创建了一个简单的示例来证明这一点不正确:
 <StackPanel>
    <ListBox>
      <ListBox.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightBlue"/>
        <!--SelectedItem without focus but doesn't really work-->
        <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Orange" />
      </ListBox.Resources>
      <ListBoxItem>
        Item 1
      </ListBoxItem>
      <ListBoxItem>
        Item 2
      </ListBoxItem>
    </ListBox>
    <TextBox></TextBox>
  </StackPanel>

如果你在.NET 4.5中运行此代码,你会发现它只改变了聚焦的颜色,而没有改变非聚焦的颜色(在.NET 4.0中可以工作)。有什么想法吗?
编辑:这似乎是List/Combo Box Background And Selected Colours Under .net 4.5的重复。

可能是.net 4.5下列表/组合框背景和选定颜色的重复问题。 - Doron Yaacoby
4个回答

16
尝试以下代码以在选中的ListBoxItem失去焦点时更改其背景颜色:
XAML
<ListBox.Resources>    
    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightBlue"/> 
    <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey }" Color="Orange" />    
</ListBox.Resources>

C#

listBox.Resources.Add(SystemColors.InactiveSelectionHighlightBrushKey, 
                      new SolidColorBrush(Colors.Orange));

希望它对你有用。


1
请查看我的答案,其中不涉及更改SystemColors的解决方案。 - bugged87

1

这一切都与控件的默认模板有关,如果它们不像在.NET 4中那样使用系统颜色,那么这将根本不会改变任何东西。


这不是一个破坏性的变更吗?而且看起来 ControlBrushKey 仍在使用。 - Doron Yaacoby
@DoronYaacoby:这并不是一个破坏性的变化,因为依赖控件模板内部的任何内容都是愚蠢的行为。这有点像通过反射调用私有方法。 - H.B.
由于这是该问题被接受且点赞最多的答案,我猜想很多人发现这个解决方案是最简单的,所以它会导致许多应用程序出现错误。但是无论如何,实现我想要的正确方法是什么? - Doron Yaacoby
@DoronYaacoby:定义您自己的模板。 - H.B.
这不是有点过度了吗?我只想改变几个颜色,我不想复制粘贴然后维护一个庞大的XAML块。 - Doron Yaacoby
@DoronYaacoby:嗯,就这方面而言,架构并不是很好,如果有一个可以调整的“ColorScheme”属性,那就太好了,但由于这不是情况,覆盖整个模板才是唯一真正干净的选择。 - H.B.

0

这是我想出来的不需要更改系统颜色或控件模板的方法。只需将ListBox包装在一个新的UserControl中。

public partial class StyledListBox : UserControl
{
    public DataTemplate ItemTemplate
    {
        get { return (DataTemplate)GetValue(ItemTemplateProperty); }
        set { SetValue(ItemTemplateProperty, value); }
    }

    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public object SelectedItem
    {
        get { return GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    public StyledListBox()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(StyledListBox), new FrameworkPropertyMetadata(null));
    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(StyledListBox), new FrameworkPropertyMetadata(null));

    public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(StyledListBox), new FrameworkPropertyMetadata(null)
    {
        BindsTwoWayByDefault = true,
        DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
    });
}

XAML:

<UserControl x:Class="StyledListBox"

     <ListBox ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type common:StyledListBox}}}"
              SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type common:StyledListBox}}}">

        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border>
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
                                             Value="True">
                                    <Setter Property="Background" Value="Red" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>

                    <ContentPresenter ContentTemplate="{Binding ItemTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StyledListBox}}}" />
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</UserControl>

然后,只需像使用ListBox一样使用包装器UserControl。您想控制的任何其他ListBox属性都可以以与示例中的ItemsSource和SelectedItem相同的方式添加到包装器中。

-2

解决方法是添加

FrameworkCompatibilityPreferences.AreInactiveSelectionHighlightBrushKeysSupported = false;

调用之前

InitializeComponent();

引发异常:“无法更改属性'AreInactiveSelectionHighlightBrushKeysSupported'。'FrameworkCompatibilityPreferences'类已被密封。” - bugged87
@bugged87 把这个放在 try/catch 块里面。我的程序使用它,在所有版本的 Windows 上看起来都很正常。 - Daniel
1
当然,添加try/catch可以处理异常,但是这段代码似乎不能使OP的代码工作。我正在Windows 8.1上使用.NET 4.5。 - bugged87

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