Wpf ListBox - 更改ContentPresenter内的默认选定项样式*

时间:2015-12-24 16:38:42

标签: wpf listbox custom-controls controltemplate

我有一个ListBox,其中每个项目都是StackPanel。 StackPanel由一个Image和一个TextBlock组成:

info

看起来像这样:

enter image description here

当用户选择一个项目时,我得到StackPanel周围的默认蓝色矩形:

enter image description here

现在,我想为所选项目制作不同的边框,但我希望 仅围绕图像

我知道如何创建一个控件模板并在ContentPresenter周围放置一个自定义边框,但这当然会围绕整个StackPanel,而不仅仅是Image。

我不知道是否可以对ContentPresenter进行更改,如果这是一个好主意。如果还有其他方法可以实现我想要的外观,那么它也会很好。

1 个答案:

答案 0 :(得分:1)

是的,ListBox自己的ContentPresenter对你正在做的事情没有帮助。你想a)消除ListBox自己的选择视觉效果,b)用更适合你的项目的DataTemplate替换它们。

默认选择视觉效果由ListBoxItem的默认模板应用。所以替换那个模板。在ListBox的资源中使用样式,将您自己的控件模板应用于ListBoxItem。不多,只提出内容,不提供选择背景。然后,您可以使用数据模板中的触发器处理选择视觉效果,其中您的图像和标签已定义,您可以将更改应用于一个而不是另一个。以下示例适用于我。

请注意,有一些摆弄Border元素上的Horizo​​ntalAlignment,使其依赖于其中的Image元素。另外,我编写了一个quickie测试视图模型,其Items属性称为Items;我假设这不是您用来填充自己的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>