我想在 WPF 窗口中向用户显示一些项目,但我想隐藏每个项目的详细信息,直到用户选择/展开项目。我想实现 Windows-Explorer-esque 功能,其中始终显示项目 Header ,并且ItemsControl
当用户单击项目的箭头时显示项目详细信息(作为 )。
有没有明显的方法可以做到这一点?或者我将不得不推出一个自定义控件?
这可以使用标准的 WPF Treeview 来完成。Josh Smith 关于简化 WPF TreeView的文章包括一个示例,展示了如何为每个TreeViewItem
.
基本方法是为 中的每个项目创建一个“虚拟”子项ViewModel
,并跟踪每个项目的展开状态TreeViewItem
。随着 aTreeViewItem
的扩展,虚拟孩子被移除并替换为真实数据。
如果您只是想自动展开/折叠项目,那么您可能需要一个触发器。例如,您可以使用扩展器并在鼠标悬停时自动扩展它。
<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 上使用相同的技巧。
我选择了ListBox
of Expander
s的路径,我对结果非常满意。
这是我的最终代码的结果:
扩展按钮的控制模板
<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>