开发者

Change color of ListBoxItem background when selected and unfocused

I am trying to change the background color of the selected items in a list box. I did that before by using

<SolidColorBrush x:Key="{x:Static SystemCo开发者_如何学Golors.ControlBrushKey}" Color="Yellow" />

which worked. But if I set IsEnabled to false on the ListBox, the whole background of the ListBox turns to the specified color of the ControlBrush. I only want to have the color changed if a ListBoxItem is selected and the ListBox has no focus.

I tried some varieties with triggers, but I can't get it to work. Even a multitrigger containing conditions with IsSelected and IsFocused didn't work for me.

Does anyone have a solution for me?

Edit: Tried the example with the ItemContainerStyle where I am getting a NullReferenceException in my project. In a new solution it works. That's the code where it doesn't work:

<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>


Add the SystemColors.ControlBrushKey to the ItemContainerStyle instead. This way it will only affect the selected items.

Edit: Here is a complete Xaml example.

<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>


  1. You cannot have both IsSelected True and IsEnabled False. Also IsFocused True and IsEnabled False.

  2. Your question talks about background color change for IsSelected as True and IsFocused as False.

In the code below (just paste ListBox XAML in youre Window code)... all these state combinations are achieved ... to check if something is focused but not selected, you would have to select some row and then use "Control + Up / Down Arrow keys" to loose focus from the selected row and focus other non-selected rows.

You will also observe that the Orange color for selected row's background would not appear (the Foreground color Cyan works though). For that background color change you must have to override the template of ListBoxItem.

    <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>

I hope this guides you in correct direction.


Resolved the problem now. Problem seemed to be that the XamlParser doesn't like it when the system color is overwritten multiple times. So I defined it like that:

<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>

Thanks for your help!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜