如果选中,则更改ListBox项目的WPF DataTemplate


89

我需要根据是否选择项目来更改列表框中项目的数据模板(选择时显示不同/更多信息)。

单击有问题的ListBox项(仅通过制表键)时,在DataTemplate(堆栈面板)的最顶层元素上没有出现GotFocus / LostFocus事件,并且我没有主意。

Answers:


182

最简单的方法是为“ ItemContainerStyle”而不是“ ItemTemplate”属性提供模板。在下面的代码中,我创建了2个数据模板:一个用于“未选中”状态,一个用于“选中”状态。然后,我为“ ItemContainerStyle”创建一个模板,该模板是包含该项目的实际“ ListBoxItem”。我将默认的“ ContentTemplate”设置为“ Unselected”状态,然后提供一个触发器,当“ IsSelected”属性为true时,该触发器将交换出模板。(注意:为简单起见,我将后面代码中的“ ItemsSource”属性设置为字符串列表)

<Window.Resources>

<DataTemplate x:Key="ItemTemplate">
    <TextBlock Text="{Binding}" Foreground="Red" />
</DataTemplate>

<DataTemplate x:Key="SelectedTemplate">
    <TextBlock Text="{Binding}" Foreground="White" />
</DataTemplate>

<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
    <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

</Window.Resources>
<ListBox x:Name="lstItems" ItemContainerStyle="{StaticResource ContainerStyle}" />

谢谢,请在您的帖子中加入<ListBox ItemContainerStyle =” {StaticResource ContainerStyle}” ItemsSource =“ {Binding MyData}” />,这样人们就不必在您的博客中进行搜索了。
Shimmy Weitzhandler,2009年

2
我在设置ListBox的ContainerStyle时遇到的一个问题是,它导致与主题不兼容。我使用了您的方法,但是当我从WPF期货应用主题时,ListBoxItems具有默认样式而不是主题样式。就我而言,黑色背景上的黑色文字和普遍的丑陋感。我仍在寻找另一种方法,也许使用DataTemplate触发器。
Benny Jobigan '02

1
另外,如果您希望新的ItemContainerStyle与主题兼容,则必须以主题中的主题为基础。为此,请BasedOn="{StaticResource {x:Type ListBoxItem}}"与ListBox一起使用。这也适用于其他控件,例如TreeView。
Benny Jobigan '02

5
在使用它的过程中,我发现我必须在“资源”部分的“样式”上方声明DataTemplates,以免发生奥秘的XAML错误。请注意。
罗伯·珀金斯

8

要在选择项目或不选择项目时设置样式,只需检索ListBoxItem您的父项,<DataTemplate>然后在样式更改时触发样式IsSelected更改。例如,下面的代码将创建一个TextBlock默认Foreground颜色为绿色的。现在,如果选中该项目,则字体将变为红色,并且当鼠标悬停在该项目上时,该字体将变为黄色。这样,您就无需为其他想要稍微改变的状态指定其他回答中建议的单独的数据模板。

<DataTemplate x:Key="SimpleDataTemplate">
    <TextBlock Text="{Binding}">
        <TextBlock.Style>
            <Style>
                <Setter Property="TextBlock.Foreground" Value="Green"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Red"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Yellow"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</DataTemplate>

1
正如我在问题中所写的那样,如果选中,我实际上会显示更多信息(“选中时显示不同/更多信息 ”)。不过,如果可以使其与某些元素的可见性切换(包括它们是否占用尺寸)一起工作,那么这将是一个可行的解决方案。一段时间未与WPF合作。
Daniel Beck

6

还应该注意的是,堆栈面板不可操纵,因此永远不会获得焦点(如果您/ really /希望将其聚焦,则将其设置为Focusable = True)。但是,在这种情况下要记住的关键是Stackpanel是TreeViewItem的子级,在这种情况下,它是ItemContainer。正如Micah所建议的那样,调整itemcontainerstyle是一个好方法。

您可能可以使用DataTemplates进行操作,诸如datatriggers之类的事情将使用RelativeSouce标记扩展来查找listviewitem

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.