概述
TreeView是常用的树状列表,在项目开发中也时常会用到,这节主要讲解treeview在wpf的基本用法!
结果演示:.

代码讲解
前台xaml:
<UserControl x:Class="Caliburn.Micro.Hello.Views.TreeViewView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="clr-namespace:Caliburn.Micro.Hello.Views"xmlns:self="clr-namespace:Caliburn.Micro.Hello.ViewModels"xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"xmlns:cal="http://www.caliburnproject.org"mc:Ignorable="d"d:DesignHeight="450" d:DesignWidth="800"><Grid><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="*"/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><dxg:TreeListControlItemsSource="{Binding EmployeeDepartments}"SelectedItem="{Binding CurrentSelectedItem}" Grid.Column="0" ><dxg:TreeListControl.View><dxg:TreeListViewAllowColumnFiltering="False"AllowConditionalFormattingMenu="False"AllowFixedColumnMenu="False"AllowRecursiveNodeChecking="True"AutoWidth="True"FetchSublevelChildrenOnExpand="False"IsColumnMenuEnabled="False"IsRowCellMenuEnabled="True"IsTotalSummaryMenuEnabled="False"KeyFieldName="Id"ParentFieldName="ParentId"ShowNodeImages="True"ShowSearchPanelMode="Always"></dxg:TreeListView></dxg:TreeListControl.View><dxg:TreeListColumnAllowEditing="False"FieldName="Employees.Name"Header="{Binding TreeTitle}" /></dxg:TreeListControl><TreeViewGrid.Column="1"Margin="10,15,10,10"ItemsSource="{Binding EmployeeDepartments}"><TreeView.ItemContainerStyle><Style TargetType="{x:Type TreeViewItem}" /></TreeView.ItemContainerStyle><TreeView.ItemTemplate><HierarchicalDataTemplate DataType="{x:Type self:EmployeeDepartment}" ItemsSource="{Binding Employees}"><StackPanel HorizontalAlignment="Stretch" Orientation="Horizontal"><CheckBox IsChecked="True"/><TextBlockVerticalAlignment="Center"FontSize="14"Text="{Binding Name}"TextTrimming="CharacterEllipsis" /></StackPanel></HierarchicalDataTemplate></TreeView.ItemTemplate></TreeView><!--最简洁写法--><TreeView Grid.Column="0" Grid.Row="1" ItemsSource="{Binding EmployeeDepartments}"><TreeView.ItemTemplate><HierarchicalDataTemplate ItemsSource="{Binding Employees}"><StackPanel><TextBlock Text="{Binding Name}"/></StackPanel></HierarchicalDataTemplate></TreeView.ItemTemplate></TreeView><TreeView Grid.Column="1" Grid.Row="1" ItemsSource="{Binding nodesCollection}"><TreeView.ItemTemplate><HierarchicalDataTemplate ItemsSource="{Binding ChildNodes}"><StackPanel HorizontalAlignment="Stretch" Orientation="Horizontal"><!--<dx:SimpleButton Glyph="{dx:DXImage Images/Arrows/Next_16x16.png}"/>--><CheckBox IsChecked="{Binding IsChecked}"cal:Message.Attach="[Event Click]=[Action CheckBox_Click($source,$eventArgs)]" /><TextBlockVerticalAlignment="Center"FontSize="14"Text="{Binding NodeName}"TextTrimming="CharacterEllipsis" /></StackPanel></HierarchicalDataTemplate></TreeView.ItemTemplate></TreeView></Grid></UserControl>
后台cs代码:
using PropertyChanged;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Windows;using System.Windows.Controls;namespace Caliburn.Micro.Hello.ViewModels{public class TreeViewViewModel : Screen, IViewModel{public TreeViewViewModel(){DisplayName = "TreeView";EmployeeDepartments = Departments.GetDepartments();//方法1//nodes = new List<TreeNode>()//{// new TreeNode(){ ParentID = 0,NodeID = 1,NodeName = "Chapter1"},// new TreeNode(){ ParentID = 0,NodeID = 2,NodeName = "Chapter2"},// new TreeNode(){ ParentID = 0,NodeID = 3,NodeName = "Chapter3"},// new TreeNode(){ ParentID = 1,NodeID = 4,NodeName = "Section1.1"},// new TreeNode(){ ParentID = 1,NodeID = 5,NodeName = "Section1.2"},// new TreeNode(){ ParentID = 2,NodeID = 6,NodeName = "Section2.1"},// new TreeNode(){ ParentID = 3,NodeID = 7,NodeName = "Section3.1"},// new TreeNode(){ ParentID = 6,NodeID = 8,NodeName = "SubSection2.1.1"},// new TreeNode(){ ParentID = 6,NodeID = 9,NodeName = "SubSection2.1.2"},// new TreeNode(){ ParentID = 2,NodeID = 10,NodeName = "Section2.2"},// new TreeNode(){ ParentID = 3,NodeID = 11,NodeName = "Section3.2"},//};//nodes = getNodes(0,nodes);//方法2nodesCollection = new ObservableCollection<TreeNode>(){new TreeNode(){NodeName = "中国人",ChildNodes = new ObservableCollection<TreeNode>(){new TreeNode(){ NodeName = "李嘉诚"},new TreeNode(){NodeName = "王健林",ChildNodes = new ObservableCollection<TreeNode>(){new TreeNode(){ NodeName = "68岁"},new TreeNode(){ NodeName = "一个儿子"},}},}},new TreeNode(){NodeName = "外国人",ChildNodes = new ObservableCollection<TreeNode>(){new TreeNode(){NodeName = "马斯克",ChildNodes = new ObservableCollection<TreeNode>(){new TreeNode(){ NodeName = "51岁"},new TreeNode(){ NodeName = "10个老婆"},}},}}};}public List<EmployeeDepartment> EmployeeDepartments { get; set; }public List<TreeNode> nodes { get; set; }public ObservableCollection<TreeNode> nodesCollection { get; set; }//private List<TreeNode> getNodes(int parentID, List<TreeNode> nodes)//{// List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();// List<TreeNode> otherNodes = nodes.Where(x => x.ParentID != parentID).ToList();// foreach (TreeNode node in mainNodes)// node.ChildNodes = getNodes(node.NodeID, otherNodes);// return mainNodes;//}public void CheckBox_Click(object sender, RoutedEventArgs e){CheckBox checkBox;if (sender is CheckBox){checkBox = sender as CheckBox;}else{return;}//SetIsChecked(nodesCollection);foreach (var childNode in nodesCollection){//SetIsChecked(childNode, checkBox.IsChecked);SetIsChecked(childNode);}}//public void SetIsChecked(ObservableCollection<TreeNode> childNodes)//{// foreach (var childNode in childNodes)// {// if(!childNode.IsChecked)// {// foreach (var child in childNode.ChildNodes)// {// child.IsChecked = false;// SetIsChecked(child.ChildNodes);// }// }// else// {// SetIsChecked(childNode.ChildNodes);// }// }//}public void SetIsChecked(TreeNode treeNode){foreach (var child in treeNode.ChildNodes){if (!treeNode.IsChecked){child.IsChecked = false;}SetIsChecked(child);}}}public static class Departments{public static List<EmployeeDepartment> GetDepartments(){List<EmployeeDepartment> departments = new List<EmployeeDepartment>();departments.Add(new EmployeeDepartment("Management", new Employee[] {new Employee(0, "Gregory S. Price")}));departments.Add(new EmployeeDepartment("Marketing", new Employee[] {new Employee(1, "Irma R. Marshall"),new Employee(2, "Brian C. Cowling"),new Employee(3, "Thomas C. Dawson"),new Employee(4, "Bryan R. Henderson"),}));departments.Add(new EmployeeDepartment("Operations", new Employee[] {new Employee(5, "John C. Powell"),new Employee(6, "Harold S. Brandes"),new Employee(7, "Jan K. Sisk"),new Employee(8, "Sidney L. Holder"),}));departments.Add(new EmployeeDepartment("Production", new Employee[] {new Employee(9, "Christian P. Laclair"),new Employee(10, "James L. Kelsey"),new Employee(11, "Howard M. Carpenter"),new Employee(12, "Jennifer T. Tapia"),}));departments.Add(new EmployeeDepartment("Finance", new Employee[] {new Employee(13, "Karen J. Kelly"),new Employee(14, "Judith P. Underhill"),new Employee(15, "Russell E. Belton"),}));return departments;}}public class Employee{public Employee(int id, string name){ID = id;Name = name;}public int ID { get; set; }public string Name { get; set; }}public class EmployeeDepartment{public string Name { get; set; }public ObservableCollection<Employee> Employees { get; }public EmployeeDepartment(string name, IEnumerable<Employee> employees){Name = name;Employees = new ObservableCollection<Employee>(employees);}}[AddINotifyPropertyChangedInterface]public class TreeNode{//public int NodeID { get; set; }//public int ParentID { get; set; }public string NodeName { get; set; }public bool IsChecked { get; set; }public ObservableCollection<TreeNode> ChildNodes { get; set; }public TreeNode(){IsChecked = true;ChildNodes = new ObservableCollection<TreeNode>();}}}
通过SetIsChecked方法实现了主节点取消勾选后,子节点也跟着去勾选,要勾选子节点,也先得选中主节点.
源码下载
链接:https://pan.baidu.com/s/1ty500tUFPNGtfnJorqaZ7A
提取码:6666