WPF: триггер для ListBoxItem.IsSelected не работает для свойства Background
Я пытаюсь изменить свойство Background
для моего ListBoxItem
с помощью триггеров в ItemContainerStyle
моего ListBox
следующим образом:
<ListBox Height="100" HorizontalAlignment="Left" Margin="107,59,0,0" Name="listBox1" VerticalAlignment="Top" Width="239">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Lightblue"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="Red"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<ListBoxItem Content="First Item"/>
<ListBoxItem Content="SecondItem"/>
<ListBoxItem Content="Third Item"/>
</ListBox.Items>
</ListBox>
Я ожидал бы, что у невыбранных элементов будет светло-синий фон, зависание элементов (т.е. когда курсор мыши над ними) будет желтым, а выбранные элементы будут красными.
Для невыделенных и зависающих элементов это работает так, как ожидалось, но выбранные элементы по-прежнему имеют свой стандартный цвет фона (то есть синий, если в списке есть фокус и светло-серый в противном случае).
Есть ли что-то, что мне не хватает? Является ли это поведение документированным где-то?
Спасибо за любой намек!
ИЗМЕНИТЬ
Я знаю о решении переопределить цвета системы по умолчанию (как описано в Изменить выбранный и не сфокусированный стиль списка, чтобы не было выделено серым цветом, спасибо в любом случае для всех отправляя это как ответ). Однако я не хочу этого делать. Меня больше интересует, почему мое решение не работает.
Я подозреваю, что стандартный ControlTemplate
of ListItem
определяет его собственные триггеры, которые, как представляется, воспринимают триггеры, определенные стилем (возможно, кто-то может подтвердить это и указать мне на какой-то ресурс, где это поведение определено),
Мое решение тем временем - определить ControlTemplate
для моего ListItem
как:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" Padding="2" SnapsToDevicePixels="true" Background="LightBlue" Margin="0">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
Ответы
Ответ 1
Немного отразится на стиле Aero, и нам объясняется, почему эта простая настройка триггера не работает.
ListBoxItem имеет ControlTemplate с триггерами, которые имеют приоритет над нашим триггером. По крайней мере, это похоже на MultiTrigger.
Мне удалось переопределить простой триггер Selected = true, но для мультитригера мне пришлось создать свой собственный ControlTemplate.
Это шаблон из стиля Aero, который показывает проблемный MultiTrigger:
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Bd" Value="{DynamicResource {x:Static HighlightBrush}}" Property="Background" />
<Setter Value="{DynamicResource {x:Static HighlightTextBrush}}" Property="Foreground" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true" />
<Condition Property="IsSelectionActive" Value="false" />
</MultiTrigger.Conditions>
<Setter TargetName="Bd" Value="{DynamicResource {x:Static ControlBrush}}" Property="Background" />
<Setter Value="{DynamicResource {x:Static ControlTextBrush}}" Property="Foreground" />
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Value="{DynamicResource {x:Static GrayTextBrush}}" Property="Foreground" />
</Trigger>
</ControlTemplate.Triggers>
<Border Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
Надеюсь, он немного разобрался. Я не могу понять, почему они слишком усложнили стиль.
Ответ 2
удалить триггер IsSelected
И добавьте в список:
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Red" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Red" />
</ListBox.Resources>
Первая кисть для сфокусированного секунды в противном случае
Ответ 3
Попробуйте добавить это к своим ресурсам окна -
<Window.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Red" />
</Window.Resources>
И удалите IsSelected Trigger из вашего кода, это не сработает, потому что каждая система имеет выделенную кисть по умолчанию в зависимости от вашей системной темы.
Вам нужно переопределить выделенную кисть в коде, чтобы она работала.
Ответ 4
Попробуйте использовать Selector.IsSelected в вашем триггере, а не в IsSelected.