public class School : ObservableObject { private bool _isOpen; /// <summary> /// 堆代码 duidaima.com /// 获取或设置是否展开 /// </summary> [System.Xml.Serialization.XmlIgnore] public bool IsOpen { get { return _isOpen; } set { Set(ref _isOpen, value); } } private bool _isSelected; /// <summary> /// 获取或设置是否被选中 /// </summary> [System.Xml.Serialization.XmlIgnore] public bool IsSelected { get { return _isSelected; } set { Set(ref _isSelected, value); } } public string SchoolID { get; set; } public string SchoolName { get; set; } public ObservableCollection<Grade> listGrade { get; set; }=new ObservableCollection<Grade>() { }; } public class Grade : ObservableObject { private bool _isOpen; [System.Xml.Serialization.XmlIgnore] public bool IsOpen { get { return _isOpen; } set { Set(ref _isOpen, value); } } private bool _isSelected; [System.Xml.Serialization.XmlIgnore] public bool IsSelected { get { return _isSelected; } set { Set(ref _isSelected, value); } } public string GradeID { get; set; } public string GradeName { get; set; } public ObservableCollection<ClassInfo> ListClass { get; set; }=new ObservableCollection<ClassInfo>() { }; } public class ClassInfo : ObservableObject { private bool _isOpen; [System.Xml.Serialization.XmlIgnore] public bool IsOpen { get { return _isOpen; } set { Set(ref _isOpen, value); } } private bool _isSelected; [System.Xml.Serialization.XmlIgnore] public bool IsSelected { get { return _isSelected; } set { Set(ref _isSelected, value); } } public string ClassID { get; set; } public string ClassName { get; set; } public ObservableCollection<Student> Students { get; set; }= new ObservableCollection<Student>() { }; } public class Student : ObservableObject { private bool _isSelected; [System.Xml.Serialization.XmlIgnore] public bool IsSelected { get { return _isSelected; } set { Set(ref _isSelected, value); } } public string Id { get; set; } public string Name { get; set; } }接下来根据定义好的Model定义层级式数据模板HierarchicalDataTemplate。
<HierarchicalDataTemplate DataType="{x:Type local:School}" ItemsSource="{Binding Path=listGrade}"> <TextBlock Text="{Binding Path=SchoolName}" /> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type local:Grade}" ItemsSource="{Binding Path=ListClass}"> <TextBlock Text="{Binding Path=GradeName}" /> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type local:ClassInfo}" ItemsSource="{Binding Path=Students}"> <TextBlock Text="{Binding Path=ClassName}" /> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type local:Student}"> <CheckBox Command="{Binding SelectChangeCommand, ElementName=self}" CommandParameter="{Binding}" IsChecked="{Binding IsSelected}"> <TextBlock Text="{Binding Path=Name}" /> </CheckBox> </HierarchicalDataTemplate>
其中最外层数据类型是School,它的下一层数据集合是ObservableCollection<Grade> listGrade,因此HierarchicalDataTemplate中的ItemsSource赋值为listGrade,这里我们再属性控件中只显示学校的名称,因此数据模板只是包含绑定了学校名称SchoolName的TextBlock,如果需要显示其他信息(比如学校年级数量或者学校图标),只需增加相应XAML元素即可。
紧接着按照这个方式定义好数据类型Grade,ClassInfo,Student的层级式数据模板即可。定义好了数据模型和相应的层级式数据模板HierarchicalDataTemplate后,就可以直接把数据元绑定到TreeView上了。假设要绑定的数据源实例是ObservableCollection<School> schools。只需如下调用即可。
<TreeView MaxHeight="480" ItemsSource="{Binding schools}" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" />这样使用TreeView是不是特别方便简洁。不用为了展示树形结构,特地定义一个递归类型的数据结构,UI展示全部交给XAML就行。JSON数据反序列化后直接绑定即可(XML或者DateSet也是类似的方法)。避免了递归遍历数据源的操作,也不用考虑递归带来的性能问题。