【问题标题】:How to Display Items and Details with Windows Explorer Expand/Collapse如何使用 Windows 资源管理器显示项目和详细信息展开/折叠
【发布时间】:2013-07-18 00:32:40
【问题描述】:

我想在 WPF 窗口中向用户显示一些项目,但我想隐藏每个项目的详细信息,直到用户选择/展开项目。我想实现 Windows-Explorer-esque 功能,其中始终显示项目标题,并且当用户单击项目的箭头时显示项目详细信息(作为 ItemsControl)。

有没有明显的方法可以做到这一点? 还是我必须拿出一个自定义控件?

【问题讨论】:

    标签: wpf .net-4.0 controls


    【解决方案1】:

    这可以通过标准的 WPF 树视图来完成。 Josh Smith 关于Simplifying the WPF TreeView 的文章包括一个示例,展示了如何为每个TreeViewItem 中的子项提供数据的延迟加载。

    基本方法是为ViewModel 中的每个项目创建一个“虚拟”子项,并跟踪每个TreeViewItem 的展开状态。随着TreeViewItem 的展开,虚拟子节点被移除并替换为真实数据。

    【讨论】:

    • 谢谢,这就是我想要的样子。然而,孩子们实际上是TreeViewItem,这意味着他们可以单独选择。如何让整个包(父级和详细信息)成为一个可选单元?
    • @Joseph 在这种情况下,您可以使它们不分层,并且只需使用 ListView 而不是 TreeView。每个 ListView 都可以通过扩展器处理,并填写它的子项..
    • 是的,我希望它看起来/功能像TreeView(单击小箭头以展开详细信息),但我可能只是很挑剔。可惜Expander这么难customize
    【解决方案2】:

    如果您只是想自动展开/折叠项目,那么您可能需要一个触发器。例如,您可以使用扩展器并在鼠标悬停时自动扩展它。

                                    <ControlTemplate.Triggers>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter Property="IsExpanded" Value="True"/>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
    

    当然,对于您希望将其设置为打开的其他触发器,可以重复此操作

            <Expander Header="Hello" IsExpanded="False">
                <Border Background="Red" Height="32"/>
                <Expander.Style>
                    <Style TargetType="Expander">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="Expander">
                                    <StackPanel>
                                        <ContentPresenter Content="{TemplateBinding Header}"/>
                                        <ContentPresenter x:Name="expander" Content="{TemplateBinding Content}" Visibility="Collapsed"/>
                                    </StackPanel>
                                    <ControlTemplate.Triggers>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter TargetName="expander" Property="Visibility" Value="Visible"/>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>                                
                    </Style>
                </Expander.Style>
            </Expander>
    

    如果您不需要像 UI 这样的完整树,那么仅拥有这些列表可能就足够了,但我很确定您也可以在 treeviewitem 上使用相同的技巧。

    【讨论】:

    • 抱歉,这是一个非常糟糕的例子,没有使用扩展器,但它确实显示了触发的想法。我会在早上更新一些更好的东西。
    • 这是一个非常巧妙的想法,但是如果项目是垂直堆叠的,并且展开/折叠功能也是垂直的,它可能会让用户感到厌烦。如果他们试图向下移动列表,那么很容易扩展许多他们不想扩展的项目。
    • 实际上,由于鼠标一次只能在一个控件上,您最终会得到与 AJAX 手风琴控件相同的操作。 :-)
    【解决方案3】:

    我选择了Expanders 路径的ListBox,我对结果非常满意。

    我的最终代码是这样结束的:

    扩展按钮的控制模板

            <ControlTemplate x:Key="TreeViewToggleButton" TargetType="{x:Type ToggleButton}">
                <Border x:Name="ToggleButtonBorder"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Padding="{TemplateBinding Padding}">
                    <Grid>
                        <Rectangle Fill="Transparent"/>
    
                        <Path x:Name="Arrow"
                              Height="10" Width="10"
                              Stroke="Black"
                              Data="m 2 1 v 8 l 4 -3.75 Z">
                        </Path>
                    </Grid>
                </Border>
    
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="Arrow" Property="Data" Value="m 2 9 h 5 v -5 Z"/>
                        <Setter TargetName="Arrow" Property="Fill" Value="Black"/>
                    </Trigger>
    
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Arrow" Property="Stroke" Value="#00A7C2"/>
                    </Trigger>
    
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsMouseOver" Value="True"/>
                            <Condition Property="IsChecked" Value="True"/>
                        </MultiTrigger.Conditions>
    
                        <Setter TargetName="Arrow" Property="Fill" Value="#00A7C2"/>
                    </MultiTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
    

    扩展器控制模板

            <ControlTemplate x:Key="TreeViewExpander" TargetType="{x:Type Expander}">
                <DockPanel>
                    <Grid DockPanel.Dock="Top">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
    
                        <ToggleButton x:Name="ExpanderButton"
                                      Grid.Column="0"
                                      Template="{StaticResource TreeViewToggleButton}"
                                      IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
                                      OverridesDefaultStyle="True"
                                      Padding="2, 0" />
                        <Label Grid.Column="1" Content="{TemplateBinding Header}"
                               Padding="0, 1"/>
                    </Grid>
    
                    <ContentPresenter x:Name="ExpanderContent"
                                      Visibility="Collapsed"
                                      DockPanel.Dock="Bottom"/>
                </DockPanel>
    
                <ControlTemplate.Triggers>
                    <Trigger Property="IsExpanded" Value="True">
                        <Setter TargetName="ExpanderContent" Property="Visibility" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
    

    在窗口中的使用

        <ListBox Grid.Row="1" DataContext="{Binding Inputs}" ItemsSource="{Binding}" ScrollViewer.CanContentScroll="False">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <Expander Template="{StaticResource TreeViewExpander}"
                                          IsExpanded="{Binding IsExpanded}">
                                    <Expander.Header>
                                        <TextBlock Text="{Binding Timestamp, StringFormat=Time: {0}}"/>
                                    </Expander.Header>
                                    <ItemsControl ItemsSource="{Binding Variables}" Margin="30 0 0 0"/>
                                </Expander>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
    
                    <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    

    【讨论】:

      猜你喜欢
      • 2020-10-26
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多