【问题标题】:Change color of ListBoxItem background when selected and unfocused选择和未聚焦时更改 ListBoxItem 背景的颜色
【发布时间】:2011-09-16 08:52:08
【问题描述】:

我正在尝试更改列表框中所选项目的背景颜色。我之前使用过

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

这很有效。但是如果我在 ListBox 上将 IsEnabled 设置为 false,则 ListBox 的整个背景将变为 ControlBrush 的指定颜色。如果选择了 ListBoxItem 并且 ListBox 没有焦点,我只想更改颜色。

我尝试了一些带有触发器的品种,但我无法让它发挥作用。即使是包含 IsSelected 和 IsFocused 条件的多重触发器也不适合我。

有人可以帮我解决吗?

编辑: 使用 ItemContainerStyle 尝试了我在项目中得到 NullReferenceException 的示例。在一个新的解决方案中它可以工作。那是它不起作用的代码:

<ItemsControl ItemsSource="{Binding Path=Classification.Values}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                                 HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsEnabled="{Binding Path=ClassificationEnabled}"
                                  VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.Row="0" x:Name="measureClassificationControl">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid Margin="2">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="{Binding Category}"/>
                                <ListBox ItemsSource="{Binding Values.SortedList}" SelectionMode="Extended" Grid.Row="1"  AlternationCount="2" 
                                     SelectionChanged="ListBox_SelectionChanged" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Height="120">
                                    <ListBox.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock TextWrapping="NoWrap" Text="{Binding Key}">
                                            <TextBlock.ToolTip>
                                                <ToolTip>
                                                     <TextBlock TextWrapping="NoWrap" Text="{Binding Value}"/>
                                                </ToolTip>
                                            </TextBlock.ToolTip>
                                        </TextBlock>
                                        </DataTemplate>
                                    </ListBox.ItemTemplate>
                                </ListBox>

                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Columns="2"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>

【问题讨论】:

    标签: wpf listbox focus listboxitem


    【解决方案1】:

    改为将SystemColors.ControlBrushKey 添加到ItemContainerStyle。这样它只会影响选定的项目。

    编辑:这是一个完整的 Xaml 示例。

    <StackPanel>
        <ListBox IsEnabled="{Binding ElementName=enabledButton, Path=IsChecked}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Style.Resources>
                        <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
                                         Color="Yellow" />
                    </Style.Resources>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBoxItem>Item 1</ListBoxItem>
            <ListBoxItem>Item 2</ListBoxItem>
            <ListBoxItem>Item 3</ListBoxItem>
            <ListBoxItem>Item 4</ListBoxItem>
            <ListBoxItem>Item 5</ListBoxItem>
        </ListBox>
        <ToggleButton Name="enabledButton" IsChecked="True" Content="IsEnabled"/>
    </StackPanel>
    

    【讨论】:

    • 感谢您的回复。我尝试了您的代码,但在控件的 InitializeComponent() 方法中出现 NullReferenceException。
    • 更新了我的答案,只需将其粘贴到新的解决方案中
    • 我试过你的代码,没有任何异常。我的猜测是来自ListBox_SelectionChanged 的例外。尝试注释掉该代码,看看您是否仍然收到异常
    • @flashflail:运气好吗?否则,尽量删除,直到异常消失。然后逐步添加它,直到它回来。然后您将其隔离并可以找出问题所在。
    • 只要您的代码不在我的 ItemsControl 中,它就可以工作。你知道为什么它在 ItemsControl 中不起作用吗?
    【解决方案2】:
    1. 您不能同时拥有IsSelected TrueIsEnabled False。还有IsFocusedTrueIsEnabledFalse

    2. 您的问题将 IsSelected 的背景颜色更改为 TrueIsFocused 为 False。

    在下面的代码中(只需将ListBox XAML 粘贴到您的窗口代码中)...所有这些状态组合都已实现...要检查是否有焦点但未选择,您必须选择一些行,然后使用“Control + 向上/向下箭头键”来松开选定行的焦点并聚焦其他未选定的行。

    您还将观察到所选行背景的Orange 颜色不会出现(尽管Foreground 颜色Cyan 有效)。对于该背景颜色更改,您必须覆盖 ListBoxItem 的 template

        <Window x:Class="WpfApplicationThemeTest.Window2"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:Microsoft.Sample.Controls"
                xmlns:sys="clr-namespace:System;assembly=mscorlib"
                Title="Window1">
            <ListBox>
                <ListBox.Resources>
                    <Style TargetType="{x:Type ListBoxItem}">
                        <Style.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <!--Condition Property="IsEnabled" Value="False"/-->
                                    <Condition Property="IsFocused" Value="True"/>
                                    <Condition Property="IsSelected" Value="False"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" Value="Yellow"/>
                            </MultiTrigger>
                            <DataTrigger Binding="{Binding}" Value="My Value6">
                                <Setter Property="IsEnabled" Value="False"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ListBox.Resources>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
                <ListBox.ItemsSource>
                    <x:Array Type="{x:Type sys:String}">
                        <sys:String>My Value1</sys:String>
                        <sys:String>My Value2</sys:String>
                        <sys:String>My Value3</sys:String>
                        <sys:String>My Value4</sys:String>
                        <sys:String>My Value5</sys:String>
                        <sys:String>My Value6</sys:String>
                        <sys:String>My Value7</sys:String>
                        <sys:String>My Value8</sys:String>
                    </x:Array>
                </ListBox.ItemsSource>
            </ListBox>
        </Window>
    

    我希望这会引导你正确的方向。

    【讨论】:

    • 感谢您的回复。我尝试像链接中描述的那样覆盖模板。但我收到 ListBoxItem 不知道 IsSelectionActive 的错误。
    【解决方案3】:

    现在解决了这个问题。问题似乎是当系统颜色被多次覆盖时,XamlParser 不喜欢它。所以我是这样定义的:

    <Window x:Class="DataGridTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit" xmlns:DataGridTest="clr-namespace:DataGridTest"
            Title="MainWindow" Height="350" Width="525">
        <Window.DataContext>
            <DataGridTest:VM />
        </Window.DataContext>
        <StackPanel>
            <ItemsControl ItemsSource="{Binding Values}">
                <ItemsControl.Resources>
                    <Style TargetType="ListBoxItem">
                        <Style.Resources>
                            <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
                                         Color="Yellow" />
                        </Style.Resources>
                    </Style>
                </ItemsControl.Resources>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <ListBox IsEnabled="{Binding ElementName=enabledButton, Path=IsChecked}">
                            <ListBoxItem>Item 1</ListBoxItem>
                            <ListBoxItem>Item 2</ListBoxItem>
                            <ListBoxItem>Item 3</ListBoxItem>
                            <ListBoxItem>Item 4</ListBoxItem>
                            <ListBoxItem>Item 5</ListBoxItem>
                        </ListBox>
    
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
    
            </ItemsControl>
            <ToggleButton Name="enabledButton" IsChecked="True" Content="IsEnabled"/>
        </StackPanel>
    </Window>
    

    感谢您的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-10
      • 2012-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-04
      相关资源
      最近更新 更多