概述
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:TreeListControl ItemsSource="{Binding EmployeeDepartments}" SelectedItem="{Binding CurrentSelectedItem}" Grid.Column="0" > <dxg:TreeListControl.View> <dxg:TreeListView AllowColumnFiltering="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:TreeListColumn AllowEditing="False" FieldName="Employees.Name" Header="{Binding TreeTitle}" /> </dxg:TreeListControl> <TreeView Grid.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"/> <TextBlock VerticalAlignment="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)]" /> <TextBlock VerticalAlignment="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); //方法2 nodesCollection = 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