c# 項目中需要實現樹狀選項的勾選,有全選,半勾選,不選的狀態。
因原控件中只有勾選和不勾選兩種狀態,所以半勾選狀態需要使用代碼繪制和自行定義。
勾選:Node.Checked=true
不勾選: Node.Checked=false
半勾選: Node.Checked=false && Node.ToolTipText="部分勾選"
注意:半勾選狀態需要重新繪制控件需要設置控件屬性DrawMode為OwnerDrawText或者OwnerDrawAll
核心邏輯一:設置父親節點的選中狀態(選中一個節點時,判斷兄弟節點是否全選;取消一個節點時,需要判斷兄弟節點是否有選中狀態和半選中狀態。由此來判斷父節點的選中狀態)
//取消節點選中狀態之后,取消所有父節點的選中狀態 private void setParentNodeCheckedState(TreeNode currNode, bool state) { TreeNode parentNode = currNode.Parent; //獲得當前節點的父節點 parentNode.Checked = state; //設置父節點的選中狀態 if (state == false) //當狀態設置為false { int flag = 0; foreach (TreeNode broNode in parentNode.Nodes) //判斷該父節點的子節點中,是否有半勾選狀態的選項 { if (broNode.Checked||broNode.ToolTipText.Equals("部分勾選")) { flag = 1; } } if (flag == 1) // 有設置父節點為半勾選狀態 { parentNode.ToolTipText = "部分勾選"; parentNode.Checked = false; } else { //設置父節點狀態為 未勾選 parentNode.ToolTipText = ""; parentNode.Checked = true; parentNode.Checked = false; //需要改變節點的Checked狀態,才能重新繪制控件; } } else { //當父節點設置為選中狀態時 int flag = 0; foreach (TreeNode broNode in parentNode.Nodes)//判斷該父節點的子節點下是否有未選中的節點。 { if (!broNode.Checked) { flag = 1; } } if (flag == 1) { parentNode.ToolTipText = "部分勾選"; parentNode.Checked = false; } else { parentNode.ToolTipText = ""; parentNode.Checked = true; } } if (currNode.Parent.Parent != null) //如果父節點之上還有父節點 { setParentNodeCheckedState(currNode.Parent, state); //遞歸調用 } }
核心邏輯二:設置子節點的選中狀態
//選中節點之后,選中節點的所有子節點 private void setChildNodeCheckedState(TreeNode currNode, bool state) { TreeNodeCollection nodes = currNode.Nodes; //獲取所有子節點 if (nodes.Count > 0) //存在子節點 foreach (TreeNode tn in nodes) { tn.Checked = state; tn.ToolTipText = ""; setChildNodeCheckedState(tn, state);//遞歸調用子節點的子節點 } }
設置控件監聽屬性AfterCheck
private void skinTreeView1_AfterCheck(object sender, TreeViewEventArgs e) { if (e.Action == TreeViewAction.ByMouse) //鼠標點擊 { //textBox1.Text = e.Node.Text; if (e.Node.Checked) //選中 { e.Node.ToolTipText = ""; //選中節點之后,選中節點的所有子節點 setChildNodeCheckedState(e.Node, true); if (e.Node.Parent != null) { setParentNodeCheckedState(e.Node, true); } } else //取消選中 { e.Node.ToolTipText = ""; //取消節點選中狀態之后,取消所有子節點的選中狀態 setChildNodeCheckedState(e.Node, false); //如果節點存在父節點,取消父節點的選中狀態 if (e.Node.Parent != null) { setParentNodeCheckedState(e.Node, false); } } } }
設置重新繪制監聽DrawNode,為半勾選狀態繪制新圖案
private void ClassTreeList_DrawNode(object sender, DrawTreeNodeEventArgs e) { if (e.Bounds.Location.X <= 0) { return; } var treeview = sender as TreeView; var brush = Brushes.Black; //黑色 if (e.Node.ToolTipText.EndsWith("部分勾選")&&e.Node.Checked==false) { //判斷為半勾選狀態 var location = e.Node.Bounds.Location; location.Offset(-10, 7); var size = new Size(7, 7); e.Graphics.FillRectangle(brush, new Rectangle(location, size)); //這里繪制的是正方形 } //繪制文本 e.Graphics.DrawString(e.Node.Text, treeview.Font, brush, e.Bounds.Left, e.Bounds.Top); }