WPF TreeView 自定义布局

在WPF(Windows Presentation Foundation)中,TreeView控件是一种常见的UI组件,用于展示层次结构的数据。默认情况下,TreeView以垂直列表的形式展示数据,但有时可能需要以不同的方式展示这些数据,例如类似于组织结构图的布局。本文将介绍如何通过自定义控件模板和样式来实现这种自定义布局。

本文假设读者已经具备了XAML、控件模板、样式、触发器、层次结构数据模板、数据绑定等WPF基础知识。如果对TreeView控件的另一种自定义布局方式感兴趣,可以阅读《WPF中TreeView控件的高级自定义布局》。

目标效果

在开始编写XAML代码之前,先来看一下想要实现的效果。如果在TreeView中填充一些简单的数据,默认情况下它看起来可能很普通。以下是“修改前”的效果图:

显然,这不是一个令人印象深刻的数据表示方式。但是,通过自定义TreeViewItem的渲染方式以及TreeView定位其项的方式,同样的TreeView控件可以变成这样:

实现原理

第一步是为TreeViewItem类创建自定义ControlTemplate。如果将该模板包装在一个类型化的Style中(即没有Key的Style),那么它将自动默认应用于每个TreeViewItem实例。TreeViewItem控件模板应该包含两个部分:一个名为'PART_Header'的ContentPresenter和一个ItemsPresenter。ContentPresenter用于显示项的内容,而ItemsPresenter用于显示其子项。

除了自定义TreeViewItem控件模板外,还需要修改TreeViewItem的ItemsPanel。为了让子项以水平行的形式显示,将TreeViewItem.ItemsPanel属性设置为具有水平方向的StackPanel。这个设置也应用在前面提到的类型化Style中。

让来看一下类型化Style的简化版本:

<Style TargetType="TreeViewItem"> <Style.Resources> </Style.Resources> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TreeViewItem"> <Grid Margin="2"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Border Name="Bd" Background="{StaticResource ItemAreaBrush}" BorderBrush="{StaticResource ItemBorderBrush}" BorderThickness="0.6" CornerRadius="8" Padding="6"> <ContentPresenter Name="PART_Header" ContentSource="Header" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Border> <ItemsPresenter Grid.Row="1" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel HorizontalAlignment="Center" IsItemsHost="True" Margin="4,6" Orientation="Horizontal" /> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style>

最后一步是使TreeView将根项水平居中。这样做将在项之间提供对称性,如上面的截图所示。这一步很简单,只需将TreeView的ItemsPanel属性设置为HorizontalAlignment设置为'Center'的Grid即可。让来看一下包含自定义TreeView的Window的XAML代码:

<Window x:Class="CustomTreeViewLayout.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:CustomTreeViewLayout" Title="Custom TreeView" Height="350" Width="780" Loaded="OnLoaded" WindowStartupLocation="CenterScreen" FontSize="11"> <TreeView Name="tree"> <TreeView.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="OrgChartTreeViewItemStyle.xaml" /> </ResourceDictionary.MergedDictionaries> <HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding ChildNodes}"> <TextBlock Text="{Binding Text}" /> </HierarchicalDataTemplate> </ResourceDictionary> </TreeView.Resources> <TreeView.ItemsPanel> <ItemsPanelTemplate> <Grid HorizontalAlignment="Center" IsItemsHost="True" /> </ItemsPanelTemplate> </TreeView.ItemsPanel> </TreeView> </Window>

不会讨论用虚拟数据填充TreeView的代码。可以在本文顶部提供的源代码下载中查看该代码(以及所有其他代码)。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485