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

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

问题描述

我有一个ListBox,其中每个项目都是一个StackPanel. StackPanel由一个图像和一个在其下面的文本块组成:

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.

推荐答案

对,列表框自己的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天全站免登陆