SelectedItem 样式不适用于带有 DataTemplate 的 ListBox?
SelectedItem Style don't work for ListBox with DataTemplate?
我有一个 ListBox
和一个 DataTemplate
,我需要更改所选项目的背景颜色。我找到了一些示例并尝试了所有示例,但可能我错过了一些要点。
我尝试更改 SolidColorBrush
资源并在 ListBox
Style
和 ListBoxItem
Style
中添加 IsSelected
的触发器但是 none 这些工作。
<Window.Resources>
<Style x:Key="ListBoxGreenStyle" TargetType="{x:Type ListBox}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightGreen" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="LightGreen" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightGreen" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightBlue" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="ListBoxDragDrop" TargetType="{x:Type ListBoxItem}">
<Setter Property="AllowDrop" Value="true"/>
<EventSetter Event="PreviewMouseMove" Handler="ListBox_PreviewMouseMove"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_PreviewMouseLeftButtonDown"/>
<EventSetter Event="Drop" Handler="ListBox_Drop"/>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightGreen" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="LightGreen" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightGreen" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightBlue" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<ListBox x:Name="lstSlides" Grid.Row="1" Grid.Column="0" Grid.RowSpan="1" Margin="5" Drop="lstSlides_Drop" DragEnter="lstSlides_DragEnter" AllowDrop="True" ItemContainerStyle="{DynamicResource ListBoxDragDrop}" SelectionMode="Extended" SelectionChanged="lstSlides_SelectionChanged" Style="{DynamicResource ListBoxGreenStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Image}" Height="32" Width="32" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Label Grid.Column="1" Content="{Binding ItemCount}" HorizontalAlignment="Center"/>
<Label Grid.Column="2" Content="{Binding Name}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
添加触发器或更改 SolidColorBrush
资源的正确 Style
是什么?
最简单的方法是摆脱您为 ListBoxItem
声明的 Style
并在 DataTemplate
中使用 DataTrigger
代替 DataTemplate
16=]:
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}" Value="True">
<Setter TargetName="grid" Property="Background" Value="Red"></Setter>
</DataTrigger>
</DataTemplate.Triggers>
(不要忘记将 x:Name="grid"
添加到您的 Grid
。)
RelativeSource
绑定让 WPF 查找可视化树,直到找到 ListBoxItem
(它会找到,因为您正在为每个 ListBoxItem
的 Content
设置模板).
这会将 ListBoxItem
的 内容 的 Background
属性 设置为 Red
。它不会改变 ListBoxItem
本身的 Background
属性!
如果那是你想要的,更复杂但最强大的选择是使用 Style
:[=36 完全覆盖 ListBoxItem
的 Template
属性 =]
<Style x:Key="{x:Type ListBoxItem}" TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" Padding="2" SnapsToDevicePixels="true">
<Border.Background>
<SolidColorBrush Color="Transparent" />
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Green" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这样,您可以在所有状态(Selected
、Unselected
、Focused
等)中重新定义每个 属性。
这只是受 this MSDN page.
启发的起点
遗憾的是,这不可能只覆盖 ControlTemplate
的一部分。如果你重写它,你需要重写它的每一部分,甚至你不想改变的部分。
您应该更改样式 "ListBoxDragDrop" 添加默认的 ItemContainerStyle。然后你可以随意改变SolidColorBrush。
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="LightGreen"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="Green"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="LightGreen"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="Green"/>
<Style x:Key="ListBoxDragDrop" TargetType="{x:Type ListBoxItem}">
<Setter Property="AllowDrop" Value="true"/>
<EventSetter Event="PreviewMouseMove" Handler="ListBox_PreviewMouseMove"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_PreviewMouseLeftButtonDown"/>
<EventSetter Event="Drop" Handler="ListBox_Drop"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="4,1"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我有一个 ListBox
和一个 DataTemplate
,我需要更改所选项目的背景颜色。我找到了一些示例并尝试了所有示例,但可能我错过了一些要点。
我尝试更改 SolidColorBrush
资源并在 ListBox
Style
和 ListBoxItem
Style
中添加 IsSelected
的触发器但是 none 这些工作。
<Window.Resources>
<Style x:Key="ListBoxGreenStyle" TargetType="{x:Type ListBox}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightGreen" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="LightGreen" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightGreen" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightBlue" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="ListBoxDragDrop" TargetType="{x:Type ListBoxItem}">
<Setter Property="AllowDrop" Value="true"/>
<EventSetter Event="PreviewMouseMove" Handler="ListBox_PreviewMouseMove"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_PreviewMouseLeftButtonDown"/>
<EventSetter Event="Drop" Handler="ListBox_Drop"/>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightGreen" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="LightGreen" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightGreen" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightBlue" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<ListBox x:Name="lstSlides" Grid.Row="1" Grid.Column="0" Grid.RowSpan="1" Margin="5" Drop="lstSlides_Drop" DragEnter="lstSlides_DragEnter" AllowDrop="True" ItemContainerStyle="{DynamicResource ListBoxDragDrop}" SelectionMode="Extended" SelectionChanged="lstSlides_SelectionChanged" Style="{DynamicResource ListBoxGreenStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Image}" Height="32" Width="32" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Label Grid.Column="1" Content="{Binding ItemCount}" HorizontalAlignment="Center"/>
<Label Grid.Column="2" Content="{Binding Name}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
添加触发器或更改 SolidColorBrush
资源的正确 Style
是什么?
最简单的方法是摆脱您为 ListBoxItem
声明的 Style
并在 DataTemplate
中使用 DataTrigger
代替 DataTemplate
16=]:
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}" Value="True">
<Setter TargetName="grid" Property="Background" Value="Red"></Setter>
</DataTrigger>
</DataTemplate.Triggers>
(不要忘记将 x:Name="grid"
添加到您的 Grid
。)
RelativeSource
绑定让 WPF 查找可视化树,直到找到 ListBoxItem
(它会找到,因为您正在为每个 ListBoxItem
的 Content
设置模板).
这会将 ListBoxItem
的 内容 的 Background
属性 设置为 Red
。它不会改变 ListBoxItem
本身的 Background
属性!
如果那是你想要的,更复杂但最强大的选择是使用 Style
:[=36 完全覆盖 ListBoxItem
的 Template
属性 =]
<Style x:Key="{x:Type ListBoxItem}" TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" Padding="2" SnapsToDevicePixels="true">
<Border.Background>
<SolidColorBrush Color="Transparent" />
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Green" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这样,您可以在所有状态(Selected
、Unselected
、Focused
等)中重新定义每个 属性。
这只是受 this MSDN page.
遗憾的是,这不可能只覆盖 ControlTemplate
的一部分。如果你重写它,你需要重写它的每一部分,甚至你不想改变的部分。
您应该更改样式 "ListBoxDragDrop" 添加默认的 ItemContainerStyle。然后你可以随意改变SolidColorBrush。
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="LightGreen"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="Green"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="LightGreen"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="Green"/>
<Style x:Key="ListBoxDragDrop" TargetType="{x:Type ListBoxItem}">
<Setter Property="AllowDrop" Value="true"/>
<EventSetter Event="PreviewMouseMove" Handler="ListBox_PreviewMouseMove"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_PreviewMouseLeftButtonDown"/>
<EventSetter Event="Drop" Handler="ListBox_Drop"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="4,1"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>