.net 如果选中,请更改 ListBox 项目的 WPF DataTemplate

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/146269/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:08:00  来源:igfitidea点击:

Change WPF DataTemplate for ListBox item if selected

.netwpf

提问by Daniel Beck

I need to change the DataTemplate for items in a ListBox depending on whether the item is selected or not (displaying different/more information when selected).

我需要根据项目是否被选中(选择时显示不同/更多信息)来更改 ListBox 中项目的 DataTemplate。

I don't get a GotFocus/LostFocus event on the top-most element in the DataTemplate (a StackPanel) when clicking the ListBox item in question (only through tabbing), and I'm out of ideas.

当单击有问题的 ListBox 项(仅通过 Tab 键)时,我没有在 DataTemplate(一个 StackPanel)的最顶层元素上收到 GotFocus/LostFocus 事件,而且我没有想法。

回答by Micah

The easiest way to do this is to supply a template for the "ItemContainerStyle" and NOT the "ItemTemplate" property. In the code below I create 2 data templates: one for the "unselected" and one for the "selected" states. I then create a template for the "ItemContainerStyle" which is the actual "ListBoxItem" that contains the item. I set the default "ContentTemplate" to the "Unselected" state, and then supply a trigger that swaps out the template when the "IsSelected" property is true. (Note: I am setting the "ItemsSource" property in the code behind to a list of strings for simplicity)

最简单的方法是为“ItemContainerStyle”而不是“ItemTemplate”属性提供模板。在下面的代码中,我创建了 2 个数据模板:一个用于“未选中”状态,一个用于“选中”状态。然后我为“ItemContainerStyle”创建一个模板,它是包含该项目的实际“ListBoxItem”。我将默认的“ContentTemplate”设置为“Unselected”状态,然后提供一个触发器,当“IsSelected”属性为真时交换模板。(注意:为简单起见,我将后面代码中的“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}" />

回答by Darien Pardinas

To set the style when the item is selected or not all you need to do is to retrieve the ListBoxItemparent in your <DataTemplate>and trigger style changes when its IsSelectedchanges. For example the code below will create a TextBlockwith default Foregroundcolor green. Now if the item gets selected the font will turn redand when the mouse is over the item will turn yellow. That way you don't need to specify separate data templates as suggested in other answers for every state you'd like to slightly change.

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

<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>

回答by Dominic Hopton

It should also be noted, that the stackpanel isn't focuable, so it's never going to get focus (set Focusable=True if you /really/ want it focused). However, the key to remember in scenarios like this is that the Stackpanel is childof the TreeViewItem, which is the ItemContainer in this case. As Micah suggests, tweaking the itemcontainerstyle is a good approach.

还应该注意的是,堆栈面板不是可聚焦的,因此它永远不会获得焦点(如果您/真​​的/想要聚焦,则设置 Focusable=True)。但是,在这种情况下要记住的关键是 Stackpanel 是TreeViewItem 的项,在这种情况下是 ItemContainer。正如 Micah 所建议的,调整 itemcontainerstyle 是一个很好的方法。

You could probably do it using DataTemplates, and things such as datatriggers which would use the RelativeSouce markup extension to look for the listviewitem

您可能可以使用 DataTemplates 以及诸如使用 RelativeSouce 标记扩展来查找 listviewitem 的数据触发器之类的东西