SelectedItem 样式不适用于带有 DataTemplate 的 ListBox?

SelectedItem Style don't work for ListBox with DataTemplate?

我有一个 ListBox 和一个 DataTemplate,我需要更改所选项目的背景颜色。我找到了一些示例并尝试了所有示例,但可能我错过了一些要点。

我尝试更改 SolidColorBrush 资源并在 ListBox StyleListBoxItem 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(它会找到,因为您正在为每个 ListBoxItemContent 设置模板).

这会将 ListBoxItem 内容 Background 属性 设置为 Red。它不会改变 ListBoxItem 本身的 Background 属性!

如果那是你想要的,更复杂但最强大的选择是使用 Style:[=36 完全覆盖 ListBoxItemTemplate 属性 =]

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

这样,您可以在所有状态(SelectedUnselectedFocused 等)中重新定义每个 属性。 这只是受 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>