WPF之层级数据模板HierarchicalDataTemplate的使用
HierarchicalDataTemplate是能够帮助层级控件显示层级数据的模板,一般多用于MenuItem和TreeViewItem,也可自己实现层级数据结构。
1、HierarchicalDataTemplate + List
数据:
using System.Collections.Generic;
namespace CSDNWpfApp.com.data
{
//公司数据
public class CompanyData
{
public string Name { get; set; }
public List<DempartmentData> DempartmentDatas { get; set; }
}
//部门数据
public class DempartmentData
{
public string Name { get; set; }
public List<EmployeeData> EmployeeDatas { get; set; }
}
//员工
public class EmployeeData
{
public string Name { get; set; }
}
}
界面:
<Window x:Class="CSDNWpfApp.TreeViewWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CSDNWpfApp" xmlns:da="clr-namespace:CSDNWpfApp.com.data"
mc:Ignorable="d"
Title="TreeViewWindow" Height="450" Width="800">
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type da:CompanyData}" ItemsSource="{Binding Path=DempartmentDatas}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type da:DempartmentData}" ItemsSource="{Binding Path=EmployeeDatas}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type da:EmployeeData}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView x:Name="treeView" HorizontalAlignment="Left" Height="350" Margin="30,30,0,0" VerticalAlignment="Top" Width="440"/>
<Button x:Name="button" Content="测试" HorizontalAlignment="Left" Margin="575,61,0,0" VerticalAlignment="Top" Width="105" Height="69" Click="Button_Click"/>
</Grid>
</Window>
说明:
- 引用了数据类的名称空间 xmlns:da=“clr-namespace:CSDNWpfApp.com.data”
- DataType指定了HierarchicalDataTemplate模板用哪种数据类型
- ItemsSource指定下一层显示哪些数据
- 内容指定了一个TextBlock,并绑定了需要显示当前指定类型数据中的属性
2、HierarchicalDataTemplate + XML
数据
<?xml version="1.0" encoding="utf-8" ?>
<root>
<Company Name="公司1">
<Dempartment Name="部门1">
<Employee Name="员工1"/>
<Employee Name="员工2"/>
</Dempartment>
<Dempartment Name="部门2">
<Employee Name="员工1"/>
<Employee Name="员工2"/>
</Dempartment>
</Company>
<Company Name="公司2">
<Dempartment Name="部门1">
<Employee Name="员工1"/>
<Employee Name="员工2"/>
</Dempartment>
<Dempartment Name="部门2">
<Employee Name="员工1"/>
<Employee Name="员工2"/>
</Dempartment>
</Company>
</root>
界面
<Window x:Class="CSDNWpfApp.TreeViewWindow2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CSDNWpfApp"
mc:Ignorable="d"
Title="TreeViewWindow2" Height="450" Width="800">
<Window.Resources>
<XmlDataProvider x:Key="xdp" Source="Companys.xml" XPath="root/Company"/>
<HierarchicalDataTemplate DataType="Company" ItemsSource="{Binding XPath=Dempartment}">
<TextBlock Text="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Dempartment" ItemsSource="{Binding XPath=Employee}">
<TextBlock Text="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Employee">
<TextBlock Text="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView x:Name="treeView" ItemsSource="{Binding Source={StaticResource xdp}}" HorizontalAlignment="Left" Height="350" Margin="30,30,0,0" VerticalAlignment="Top" Width="440"/>
</Grid>
</Window>
说明
- 使用XmlDataProvider作为数据源
- DataType 可以把xml数据中的元素作为当前数据类型,这样元素的子节点和Attribute可以使用XPath来访问
- ItemsSource 通过XPath指定下一级需要显示的元素
- 显示内容指定了一个TextBlock 通过XPath绑定当前数据类型需要显示的属性
3、TreeView + HierarchicalDataTemplate + ObservableCollection
上面两个例子均为学习过程中所需要的Demo,在《深入浅出WPF》的第11章有类似的Demo,但在具体项目中,HierarchicalDataTemplate常与TreeView 构建层级结构。且常常需要界面显示的数据动态刷新,则会使用到ObservableCollection集合。
具体使用看如下代码。
数据类
/// <summary>
/// 数据类
/// </summary>
public class UIWindowsHelper : INotifyPropertyChanged
{
private ObservableCollection<Project> _projects = new ObservableCollection<Project>();
public ObservableCollection<Project> Projects
{
get { return _projects; }
set
{
if (_projects == value)
return;
_projects = value;
OnPropertyChanged("Projects");
}
}
//......
}
/// <summary>
/// Project类
/// </summary>
public class Project : ICloneable
{
private string _projectName = "";
public string ProjectName
{
get { return _projectName; }
set
{
if (_projectName != value)
{
_projectName = value;
OnPropertyChanged("ProjectName");
}
}
}
private ObservableCollection<SubProject> _listSubProjects = new ObservableCollection<SubProject>();
public ObservableCollection<SubProject> ListSubProjects
{
get { return _listSubProjects; }
set
{
_listSubProjects = value;
OnPropertyChanged("ListSubProjects");
}
}
//......
}
/// <summary>
/// SubProject类
/// </summary>
public class Project : ICloneable
{
private string _subProjectName;
public string subProjectName
{
get { return _subProjectName; }
set {
_subProjectName = value;
OnPropertyChanged("subProjectName");
}
}
//......
}
界面
<TreeView x:Name="ProjectsTreeView" ItemsSource="{Binding Projects,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" BorderThickness="1,0,1,1" BorderBrush="#EEEEEE" AllowDrop="True" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ListSubProjects, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<StackPanel x:Name="myBorder">
<Label Content="{Binding ProjectName,Mode=TwoWay}" />
</StackPanel>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="IsExpanded" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Label Name="myLabel" Content ="{Binding subProjectName,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" TargetName="myLabel" Value="#f75d00"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
设置数据绑定到界面的方法有多种可以实现,如在*.xaml.cs文件中,设置this.DataContext。