wpf 如果选择了该项目,则更改 ListBoxItem 中的 DataTemplate 样式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14542682/
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-13 07:14:32  来源:igfitidea点击:

Change DataTemplate style in ListBoxItem if the item is selected

wpfxamltriggerslistboxstyles

提问by Hannish

I have a listbox with an expander inside the ItemTemplate. I managed to bind the expander's IsExpanded property to the ListBoxItem's IsSelected property ok. Now I want to apply a style to the ListBoxItem's content also bound to the IsSelected property.

我在 ItemTemplate 中有一个带有扩展器的列表框。我设法将扩展器的 IsExpanded 属性绑定到 ListBoxItem 的 IsSelected 属性。现在我想将样式应用于 ListBoxItem 的内容,也绑定到 IsSelected 属性。

    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border Name="myBorder">
                    <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Description}" />
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Date:"/>
                        <TextBlock Text="{Binding Date}"/>
                    </StackPanel>
                    <dx:DXExpander Name="expanderDetails" 
                              IsExpanded="{Binding Mode=TwoWay, Path=IsSelected,
                              RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Count:"/>
                            <TextBlock Text="{Binding Count}"/>
                        </StackPanel>
                    </dx:DXExpander>
                </StackPanel>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>

What I want to do is somehow set the style of the "myBorder" Border to "NotSelectedBorderStyle" for unselected ListBoxItems, and to "SelectedBorderStyle" for the SelectedItem (ListBox with single selection).

我想要做的是以某种方式将“myBorder”边框的样式设置为“NotSelectedBorderStyle”,用于未选中的 ListBoxItems,并将 SelectedBorderStyle 设置为 SelectedItem(单选列表框)。

FYI, the styles define background, border and that kind of stuff, just to make the clear which item is selected, nothing fancy in these styles.

仅供参考,样式定义了背景、边框和那种东西,只是为了明确选择了哪个项目,这些样式没有什么特别之处。

I tried the accepted answer herebut if I completely switch styles I loose the nice expanding animation my DXExpander has.

我在这里尝试了接受的答案,但如果我完全切换样式,我会失去 DXExpander 拥有的漂亮的扩展动画。

I guess there must be some solution using triggers, but I can't just hit the right spot.

我想一定有一些使用触发器的解决方案,但我不能只是找到正确的位置。

回答by Hannish

Finally I got it, I'm posting it here in the hope that this will save someone else time and pain :-P

终于我明白了,我把它贴在这里,希望这能节省别人的时间和痛苦:-P

This code does some additional things: the EventSetter and the corresponding Handler method are there to capture clicks to the elements inside the DataTemplate, in order to select the ListBoxItem which contains the element (if you don't you might type text inside an item, while a different one is selected).

这段代码做了一些额外的事情:EventSetter 和相应的 Handler 方法用于捕获对 DataTemplate 内元素的点击,以便选择包含该元素的 ListBoxItem(如果不这样做,您可能会在项目内键入文本,而选择了一个不同的)。

The inner Border ("myBorder") is just a container for the stackpanels, I had to wrap everything inside another border ("backgroundBorder") which gets the style changed when the ListBoxItem gets selected.

内部边框(“myBorder”)只是堆栈面板的容器,我必须将所有内容都包裹在另一个边框(“backgroundBorder”)中,当 ListBoxItem 被选中时,它的样式会发生变化。

    <Style x:Key="FocusedContainer" TargetType="{x:Type ListBoxItem}">
        <Setter Property="Background" Value="LightGray"/>
        <EventSetter Event="GotKeyboardFocus" Handler="OnListBoxItemContainerFocused" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border x:Name="backgroundBorder" Width="Auto" Style="{StaticResource NotSelectedBorderStyle}">
                        <ContentPresenter Content="{TemplateBinding Content}">
                            <ContentPresenter.ContentTemplate>
                                <DataTemplate>
                                    <Border Name="myBorder">
                                         <StackPanel Orientation="Vertical">
                                               <TextBlock Text="{Binding Description}" />
                                         <StackPanel Orientation="Horizontal">
                                               <TextBlock Text="Date:"/>
                                               <TextBlock Text="{Binding Date}"/>
                                         </StackPanel>
                                         <dx:DXExpander Name="expanderDetails" 
                                             IsExpanded="{Binding Mode=TwoWay, Path=IsSelected,
                                             RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}">
                                                <StackPanel Orientation="Horizontal">
                                                     <TextBlock Text="Count:"/>
                                                     <TextBlock Text="{Binding Count}"/>
                                                </StackPanel>
                                         </dx:DXExpander>
                                       </StackPanel>
                                    </Border>
                                </DataTemplate>
                            </ContentPresenter.ContentTemplate>
                        </ContentPresenter>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="backgroundBorder" Property="Style" Value="{StaticResource SelectedBorderStyle}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Then I set the ItemContainerStyle in my ListBox to the above style:

然后我将 ListBox 中的 ItemContainerStyle 设置为上述样式:

<ListBox Background="#7FFFFFFF" HorizontalContentAlignment="Stretch" 
         ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True"
         ItemContainerStyle="{StaticResource FocusedContainer}"/>

To finish, the code behind for the GotKeyBoardFocus handler:

最后,GotKeyBoardFocus 处理程序背后的代码:

    private void OnListBoxItemContainerFocused(object sender, RoutedEventArgs e)
    {
        (sender as ListBoxItem).IsSelected = true;
    }

A mess in code, but pretty neat in the UI. Hope this helps someone!

代码混乱,但 UI 非常整洁。希望这对某人有帮助!