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

标签 wpf xaml triggers listbox styles

我在 ItemTemplate 中有一个带有扩展器的列表框。我成功地将扩展器的 IsExpanded 属性绑定(bind)到 ListBoxItem 的 IsSelected 属性。现在我想将样式应用到也绑定(bind)到 IsSelected 属性的 ListBoxItem 内容。

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

我想要做的是以某种方式将“myBorder”边框的样式设置为“NotSelectedBorderStyle”(对于未选择的ListBoxItems),以及为“SelectedBorderStyle”对于SelectedItem(具有单选的ListBox)。

仅供引用,样式定义了背景、边框之类的东西,只是为了清楚地表明选择了哪个项目,这些样式没有什么花哨的。

我尝试了 accepted answer here但如果我完全切换样式,我就会失去 DXExpander 所拥有的漂亮的扩展动画。

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

最佳答案

终于我明白了,我将其发布在这里,希望这会节省其他人的时间和痛苦:-P

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

内部边框(“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>

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

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

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

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

代码困惑,但用户界面非常整洁。希望这对某人有帮助!

关于wpf - 如果选择了该项目,则更改 ListBoxItem 中的 DataTemplate 样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14542682/

相关文章:

WPF 弹出窗口出现在其他桌面窗口上,如何只出现在 WPF 主窗口的顶部?

c# - 当弹出窗口中的数据网格捕获鼠标时,wpf 弹出窗口不会自动关闭

c# - 将 RowSplitter 与 UniformGrid 或其他东西一起使用以获得所需的结果

c# - Roslyn:从代码分析器访问部分类的 XAML

mysql - 通过触发器使用前一行和当前行的数据将总和插入到数据库的列中

mysql:自动将某些列的秒数转换为小时数

postgresql - 在 PostgreSQL 中删除触发器的正确​​方法

c# - 在 WPF 中显示动画 gif

wpf - tabControl 中的多个 userControl 实例

c# - 使用 TextBox 在 WPF slider 上呈现刻度数