Wpf ListBox – change default selected-item style *inside* the ContentPresenter

前端 未结 1 1861
渐次进展
渐次进展 2021-01-28 00:46

I have a ListBox in which each item is a StackPanel. The StackPanel consist of an Image and a TextBlock below it:



    

        
相关标签:
1条回答
  • 2021-01-28 01:18

    Right, the ListBox's own ContentPresenter isn't helpful for what you're doing. You want to a) eliminate the ListBox's own selection visuals and b) replace them with something more suitable in the DataTemplate for your items.

    The default selection visual is applied by the default template for ListBoxItem. So replace that template. Using a Style in the resources for your ListBox, apply your own control template to ListBoxItem. Not much to it, just present the content and don't provide a selection background. Then you handle the selection visuals with a trigger in your data template, where your image and your label are defined and you can apply changes to one and not the other. The below example works for me.

    Note that there's some fiddling with the HorizontalAlignment on the Border element to make it cling to the Image element within it. Also, I wrote a quickie test viewmodel whose Items property is called Items; I assume this is not the name of the collection member you're using to populate your own ListBox.

    <ListBox
        Margin="8"
        ItemsSource="{Binding Items}"
        >
        <ListBox.Resources>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <Grid>
                                <ContentPresenter />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.Resources>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Border
                        x:Name="HighlightBorder"
                        BorderThickness="4"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Top"
                        Margin="10"
                        >
                        <Border.Style>
                            <Style TargetType="Border">
                                <!-- MUST set default BorderBrush via a style, if you set it at all. 
                                As an attribute on the Border tag, it would override the effects of 
                                the trigger below. 
                                -->
                                <Setter Property="BorderBrush" Value="Transparent" />
                            </Style>
                        </Border.Style>
                        <Image Source="{Binding ImageFilePath}" />
                    </Border>
                </Grid>
                <DataTemplate.Triggers>
                    <DataTrigger 
                        Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" 
                        Value="True">
                        <Setter TargetName="HighlightBorder" Property="BorderBrush" Value="Orange" />
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    
    0 讨论(0)
提交回复
热议问题