WPF
中的 TreeView
控件用于显示分层结构的数据,如文件夹结构、组织结构图等。它允许用户通过展开和折叠节点来查看和隐藏其子节点。本文将详细介绍如何在 WPF
中使用 TreeView
,从基础使用到高级功能。
目录
1. 基本使用
在 XAML 中定义 TreeView
TreeView
的基本用法是将 TreeViewItem
直接嵌套到 TreeView
中。这是最简单的静态树结构定义方法。
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TreeView Example" Height="300" Width="300">
<Grid>
<TreeView>
<TreeViewItem Header="Fruits">
<TreeViewItem Header="Apple"/>
<TreeViewItem Header="Banana"/>
</TreeViewItem>
<TreeViewItem Header="Vegetables">
<TreeViewItem Header="Carrot"/>
<TreeViewItem Header="Broccoli"/>
</TreeViewItem>
</TreeView>
</Grid>
</Window>
运行效果
用户可以展开和折叠 “Fruits” 和 “Vegetables” 节点,查看子项。
动态添加 TreeViewItem
可以通过代码动态添加项到 TreeView
中:
TreeViewItem fruits = new TreeViewItem() { Header = "Fruits" };
fruits.Items.Add(new TreeViewItem() { Header = "Apple" });
fruits.Items.Add(new TreeViewItem() { Header = "Banana" });
TreeViewItem vegetables = new TreeViewItem() { Header = "Vegetables" };
vegetables.Items.Add(new TreeViewItem() { Header = "Carrot" });
vegetables.Items.Add(new TreeViewItem() { Header = "Broccoli" });
treeView.Items.Add(fruits);
treeView.Items.Add(vegetables);
2. 通过数据绑定实现 TreeView
在实际应用中,数据可能来源于数据库、文件系统等,不可能手动定义所有项。因此,TreeView
支持通过数据绑定来动态加载节点。
示例:绑定到一个简单的对象集合
数据模型
public class Category
{
public string Name { get; set; }
public List<Category> SubCategories { get; set; }
}
定义数据
public MainWindow()
{
InitializeComponent();
var categories = new List<Category>
{
new Category
{
Name = "Fruits",
SubCategories = new List<Category>
{
new Category { Name = "Apple" },
new Category { Name = "Banana" }
}
},
new Category
{
Name = "Vegetables",
SubCategories = new List<Category>
{
new Category { Name = "Carrot" },
new Category { Name = "Broccoli" }
}
}
};
treeView.ItemsSource = categories;
}
绑定 XAML
为了让 TreeView
正确显示层次数据,我们需要使用 HierarchicalDataTemplate
来定义如何展示父子关系。
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TreeView Binding" Height="300" Width="300">
<Grid>
<TreeView x:Name="treeView" ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubCategories}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
结果
TreeView
通过ItemsSource
绑定到categories
列表。
3. HierarchicalDataTemplate
模板
HierarchicalDataTemplate
是 TreeView
最重要的模板,它定义了如何展示数据的层次结构。每个节点都可以有自己的子节点,它们也可以被绑定到数据源。
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubCategories}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
结果
HierarchicalDataTemplate
使用ItemsSource="{Binding SubCategories}"
来定义子项的绑定。
自定义模板
可以在 HierarchicalDataTemplate
中自定义每个节点的外观。例如,为每个项添加一个图标:
<HierarchicalDataTemplate ItemsSource="{Binding SubCategories}">
<StackPanel Orientation="Horizontal">
<Image Source="icon.png" Width="16" Height="16"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</StackPanel>
</HierarchicalDataTemplate>
4. 使用 MVVM 实现 TreeView
在 MVVM
(Model-View-ViewModel)模式下,通过 ViewModel
来管理 TreeView
的数据和行为。
定义 ViewModel
public class CategoryViewModel
{
public ObservableCollection<Category> Categories { get; set; }
public CategoryViewModel()
{
Categories = new ObservableCollection<Category>
{
new Category
{
Name = "Fruits",
SubCategories = new List<Category>
{
new Category { Name = "Apple" },
new Category { Name = "Banana" }
}
},
new Category
{
Name = "Vegetables",
SubCategories = new List<Category>
{
new Category { Name = "Carrot" },
new Category { Name = "Broccoli" }
}
}
};
}
}
绑定到 View
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TreeView MVVM" Height="300" Width="300">
<Grid>
<TreeView ItemsSource="{Binding Categories}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubCategories}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
设置 DataContext
在 MainWindow.xaml.cs
中设置 DataContext
为 CategoryViewModel
:
public MainWindow()
{
InitializeComponent();
DataContext = new CategoryViewModel();
}
5. 自定义 TreeViewItem
样式
你可以通过自定义 TreeViewItem
的样式来改变 TreeView
的外观。例如,改变节点的背景颜色或文本样式:
<Style TargetType="TreeViewItem">
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
自定义选择项的样式
可以自定义选中项的背景颜色:
<Style TargetType="TreeViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</Style.Triggers>
</Style>
6. 事件处理
你可以通过事件处理器来处理 TreeView
的交互,比如节点的选择、展开或折叠。
SelectedItemChanged
事件
<TreeView SelectedItemChanged="TreeView_SelectedItemChanged">
<!-- TreeView 定义 -->
</TreeView>
在后台代码中处理事件
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var selectedItem = e.NewValue as Category;
MessageBox.Show($"You selected: {selectedItem?.Name}");
}
7. 完整示例
结合上面的知识,我们可以构建一个完整的 TreeView
应用:
XAML 代码
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml"
Title="TreeView Example" Height="300" Width="300">
<Grid>
<TreeView ItemsSource="{Binding Categories}"
SelectedItemChanged="TreeView_SelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubCategories}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
后台代码
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new CategoryViewModel();
}
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var selectedItem = e.NewValue as Category;
MessageBox.Show($"You selected: {selectedItem?.Name}");
}
}
8. 总结
WPF
中的 TreeView
是一个功能强大的控件,适合用于显示层次化数据。通过数据绑定、HierarchicalDataTemplate
和 MVVM
模式,可以实现动态、灵活且易于维护的树结构显示。同时,通过自定义样式和事件处理,可以打造出个性化的用户界面。