Wpf ListBox – 在 ContentPresenter *内部更改默认选定项样式 [英] Wpf ListBox – change default selected-item style *inside* the ContentPresenter

查看:44
本文介绍了Wpf ListBox – 在 ContentPresenter *内部更改默认选定项样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ListBox,其中每个项目都是一个 StackPanel.StackPanel 由一个 Image 和它下面的一个 TextBlock 组成:

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

<ListBox.ItemTemplate>

    <DataTemplate>

        <StackPanel Margin="10">

            <Image>
                <Image.Source>
                    <BitmapImage UriSource="{Binding Path=ImageFilePath}"/>
                </Image.Source>
            </Image>

            <TextBlock Text="Title" TextAlignment="Center"/>

        </StackPanel>

   </DataTemplate>

</ListBox.ItemTemplate>

看起来像这样:

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

When the user select an item, I get the default blue rectangle that surround the StackPanel:

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

Now, I want to make a different border for the selected-item, but I want it to surround only the image.

我知道如何制作控件模板并在 ContentPresenter 周围放置自定义边框,但是这当然会包围整个 StackPanel,而不仅仅是 Image.

I know how to make a control template and put a custom border around the ContentPresenter, but this, of course, will surround the whole StackPanel, not only the Image.

我不知道是否可以更改 ContentPresenter,也不知道这是否是个好主意.如果有其他方法可以实现我想要的外观,那也可以.

I don’t know if making changes to the ContentPresenter is possible, and if it is a good idea at all. If there is other way to achieve the look I want, it will be fine as well.

推荐答案

没错,ListBox 自己的 ContentPresenter 对你正在做的事情没有帮助.您希望 a) 消除 ListBox 自己的选择视觉效果,并 b) 用 DataTemplate 中更适合您的项目的内容替换它们.

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.

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

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.

请注意,对 Border 元素上的 Horizo​​ntalAlignment 进行了一些调整,以使其紧贴其中的 Image 元素.另外,我写了一个快速测试视图模型,它的 Items 属性称为 Items;我假设这不是您用来填充您自己的 ListBox 的集合成员的名称.

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>

这篇关于Wpf ListBox – 在 ContentPresenter *内部更改默认选定项样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆