Изменение цвета фона ListBoxItem при выделении и расфокусировке

Я пытаюсь изменить цвет фона выбранных элементов в списке. Я делал это раньше, используя

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

который работал. Но если я установлю IsEnabled в false в ListBox, весь фон 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>

person Kai    schedule 16.09.2011    source источник


Ответы (3)


Вместо этого добавьте 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>
person Fredrik Hedblad    schedule 16.09.2011
comment
Спасибо за ваш ответ. Я пробовал ваш код, но получаю исключение NullReferenceException в методе InitializeComponent () элемента управления. - person Kai; 16.09.2011
comment
Обновил мой ответ, просто вставьте его в новое решение - person Fredrik Hedblad; 16.09.2011
comment
Я попробовал ваш код и не получил исключения. Я предполагаю, что исключение исходит от ListBox_SelectionChanged. Попробуйте закомментировать этот код и посмотреть, возникает ли по-прежнему исключение. - person Fredrik Hedblad; 16.09.2011
comment
@flashflail: Удачи? В противном случае старайтесь удалить как можно больше, пока исключение не исчезнет. Затем добавляйте его, шаг за шагом, пока он не вернется. Затем вы изолировали его и можете понять, в чем проблема. - person Fredrik Hedblad; 16.09.2011
comment
Пока ваш код не находится в моем ItemsControl, он работает. Вы знаете, почему это не работает внутри ItemsControl? - person Kai; 16.09.2011
comment
@flashflail: Значит, как только вы добавите мое дополнение, вы получите это исключение? - person Fredrik Hedblad; 16.09.2011

  1. У вас не может быть одновременно IsSelected True и IsEnabled False. Также IsFocused True и IsEnabled False.

  2. В вашем вопросе говорится об изменении цвета фона для IsSelected как True и IsFocused как False.

В приведенном ниже коде (просто вставьте ListBox XAML в ваш код окна) ... все эти комбинации состояний достигнуты ... чтобы проверить, сфокусировано ли что-то, но не выбрано, вам нужно будет выбрать некоторую строку и затем использовать "Control + Up" / Клавиши со стрелкой вниз ", чтобы отвлечься от выбранной строки и сфокусироваться на других невыделенных строках.

Вы также заметите, что цвет Orange для фона выбранной строки не отображается (хотя Foreground цвет Cyan работает). Для этого изменения цвета фона вам необходимо переопределить шаблон из 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>

Я надеюсь, что это приведет вас в правильном направлении.

person WPF-it    schedule 16.09.2011
comment
Спасибо за ваш ответ. Я попытался переопределить шаблон, как описано в ссылке. Но я получаю сообщение об ошибке, что IsSelectionActive не известен ListBoxItem. - person Kai; 16.09.2011

Решил проблему сейчас. Проблема, казалось, заключалась в том, что 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>

Спасибо за вашу помощь!

person Kai    schedule 16.09.2011