C# TreeView使用技巧
节点勾选设置
TreeView树中节点勾选要求:
1、不选中一个节点,则其所有的子节点都不被选中。
2、选中一个节点,则其所有的子节点都被选中。
3、当一个节点的所有子节点都没有被选中时,该节点也没有被选中。
4、当一个节点的所有子节点中有一个被选中时,则该节点也被选中。
代码中对事件参数e.Action的判断,可以避免在改变节点的Checked的状态时,再次进入AfterCheck(),这样当在AfterCheck()中有其他逻辑响应时,可以做到每次勾选时,其他逻辑也只响应一次。
参考代码:
private void treeView_AfterCheck(object sender, TreeViewEventArgs e) { //通过鼠标或者键盘触发事件,防止修改节点的Checked状态时候再次进入 if (e.Action == TreeViewAction.ByMouse || e.Action == TreeViewAction.ByKeyboard) { SetChildNodeCheckedState(e.Node, e.Node.Checked); SetParentNodeCheckedState(e.Node, e.Node.Checked); } } //设置子节点状态 private void SetChildNodeCheckedState(TreeNode currNode, bool isCheckedOrNot) { if (currNode.Nodes == null) return; //没有子节点返回 foreach (TreeNode tmpNode in currNode.Nodes) { tmpNode.Checked = isCheckedOrNot; SetChildNodeCheckedState(tmpNode, isCheckedOrNot); } } //设置父节点状态 private void SetParentNodeCheckedState(TreeNode currNode, bool isCheckedOrNot) { if (currNode.Parent == null) return; //没有父节点返回 if (isCheckedOrNot) //如果当前节点被选中,则设置所有父节点都被选中 { currNode.Parent.Checked = isCheckedOrNot; SetParentNodeCheckedState(currNode.Parent, isCheckedOrNot); } else //如果当前节点没有被选中,则当其父节点的子节点有一个被选中时,父节点被选中,否则父节点不被选中 { bool checkedFlag = false; foreach (TreeNode tmpNode in currNode.Parent.Nodes) { if (tmpNode.Checked) { checkedFlag = true; break; } } currNode.Parent.Checked = checkedFlag; SetParentNodeCheckedState(currNode.Parent, checkedFlag); } }
TreeView隐藏部分节点
WinForm中的TreeView没法根据每个节点的情况设置是否有checkbox,只能用CheckBoxes设置整个树是否有Checkbox,可通过如下方式隐藏部分节点的checkbox。
this.treeView1.CheckBoxes = true; this.treeView1.DrawMode = TreeViewDrawMode.OwnerDrawAll; this.treeView1.DrawNode += new DrawTreeNodeEventHandler(treeView1_DrawNode);
隐藏节点:
void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e) { //隐藏节点前的checkbox if (e.Node.Level == 0 || e.Node.Level == 1) HideCheckBox(this.treeView1, e.Node); e.DrawDefault = true; } [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)] private struct TVITEM { public int mask; public IntPtr hItem; public int state; public int stateMask; [MarshalAs(UnmanagedType.LPTStr)] public string lpszText; public int cchTextMax; public int iImage; public int iSelectedImage; public int cChildren; public IntPtr lParam; } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref TVITEM lParam); private const int TVIF_STATE = 0x8; private const int TVIS_STATEIMAGEMASK = 0xF000; private const int TV_FIRST = 0x1100; private const int TVM_SETITEM = TV_FIRST + 63; private void HideCheckBox(TreeView tvw, TreeNode node) { TVITEM tvi = new TVITEM(); tvi.hItem = node.Handle; tvi.mask = TVIF_STATE; tvi.stateMask = TVIS_STATEIMAGEMASK; tvi.state = 0; SendMessage(tvw.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi); }
TreeView递归加载节点
C#遍历指定文件夹下所有子文件夹及文件并添加到目录树:
private void Form1_Load(object sender, EventArgs e) { TreeNode root = new TreeNode(); //根目录名称 root.Text = "目录"; //根目录路径 GetFiles(@"E:\Tools", root); treeView1.Nodes.Add(root); } private void GetFiles(string filePath, TreeNode node) { DirectoryInfo folder = new DirectoryInfo(filePath); node.Text = folder.Name; node.Tag = folder.FullName; FileInfo[] chldFiles = folder.GetFiles("*.*"); foreach (FileInfo chlFile in chldFiles) { TreeNode chldNode = new TreeNode(); chldNode.Text = chlFile.Name; chldNode.Tag = chlFile.FullName; node.Nodes.Add(chldNode); } DirectoryInfo[] chldFolders = folder.GetDirectories(); foreach (DirectoryInfo chldFolder in chldFolders) { TreeNode chldNode = new TreeNode(); chldNode.Text = folder.Name; chldNode.Tag = folder.FullName; node.Nodes.Add(chldNode); GetFiles(chldFolder.FullName, chldNode); } }