using System.Drawing; using System.Windows.Forms; using System.ComponentModel; namespace SimpleCustomControl { [ToolboxBitmap(typeof(TreeView))] public partial class MyTreeView : TreeView { private int imageWidth = 0x12; private bool isFirstNodeDifferent = true; [Category("行为"), DefaultValue(true), Description("确定根节点第一个节点是否作为取消所择使用。")] public bool IsFirstNodeDifferent { get { return isFirstNodeDifferent; } set { isFirstNodeDifferent = value; } } public MyTreeView() { InitializeComponent(); // 如果更改 ImageList 中图片大小,此处设置可能有用.未测试.可注释掉. imageWidth = imageList1.ImageSize.Width + 2; } //规则1:取消选定 //规则1.1:检查是否有子节点,需清除所有子节点的选定状态; //规则1.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态 //规则2:选定 //规则2.1:检查是否有子节点,设置所有子节点为选定状态 //规则2.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态 /// <summary> /// 鼠标点击节点触发事件 /// </summary> private void MyTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Button == MouseButtons.Left) { Rectangle rc = e.Node.Bounds; rc = new Rectangle(rc.X - imageWidth, rc.Y, rc.Width + imageWidth, rc.Height); if (rc.Contains(e.Location)) { if (isFirstNodeDifferent && e.Node.Level == 0 && e.Node.Index == 0) NodeUnSelected(); else NodeClick(e.Node); } } } /// <summary> /// 节点点击 /// </summary> /// <param name="tn">点击的节点</param> public void NodeClick(TreeNode tn) { if (tn.ImageIndex == 2) { NodeUnSelected(tn); } else { NodeSelected(tn); } } /// <summary> /// 不管现在节点状态 /// 将节点设置为选中 /// </summary> /// <param name="tn">待更改状态的节点</param> public void NodeSelected(TreeNode tn) { tn.SelectedImageIndex = 2; tn.ImageIndex = 2; SetNodeImg21(tn); SetNodeImg22(tn); } /// <summary> /// 不管现在节点状态 /// 去掉节点选中状态 /// </summary> /// <param name="tn">待更改状态的节点</param> public void NodeUnSelected(TreeNode tn) { tn.SelectedImageIndex = 0; tn.ImageIndex = 0; SetNodeImg11(tn); SetNodeImg12(tn); } /// <summary> /// 查找节点状态 是否被选中 /// </summary> /// <param name="tn">查看的节点</param> /// <returns>节点是否被选中</returns> public bool NodeIsChecked(TreeNode tn) { if (tn.ImageIndex == 1 || tn.ImageIndex == 2) return true; return false; } private bool nodeIsAllChecked; /// <summary> /// 返回整个TreeView 选中状态 /// </summary> /// <returns>返回选中状态信息</returns> [Browsable(false)] public bool NodeIsAllChecked { get { if (isFirstNodeDifferent) { // 两种方式 两种效率 未测试哪个更效率 //foreach (TreeNode tn in Nodes) //{ // if (tn.Index != 0 && NodeCheckState(tn) != CheckState.Checked) // return false; //} int count = Nodes.Count; for (int i = 1; i < count; i++) { if (NodeCheckState(Nodes[i]) != CheckState.Checked) return false; } } else { foreach (TreeNode tn in Nodes) { if (NodeCheckState(tn) != CheckState.Checked) return false; } } return true; } } /// <summary> /// 返回指定节点选中状态 /// 有三种状态 Checked 选中 Indeterminate 部分选中 Unchecked 未选中 /// </summary> /// <param name="tn">节点是否被选中</param> /// <returns>返回选中状态信息</returns> public CheckState NodeCheckState(TreeNode tn) { switch (tn.ImageIndex) { case 1: return CheckState.Indeterminate; case 2: return CheckState.Checked; case 0: default: return CheckState.Unchecked; } } /// <summary> /// 将所有子节点全不选 /// </summary> public void NodeUnSelected() { foreach (TreeNode tn in this.Nodes) { NodeUnSelected(tn); } } /// <summary> /// 将所有子节点全选 /// </summary> public void NodeSelected() { foreach (TreeNode tn in this.Nodes) { NodeSelected(tn); } if (isFirstNodeDifferent && Nodes.Count > 0) { Nodes[0].SelectedImageIndex = 0; Nodes[0].ImageIndex = 0; } } //设置节点选定状态: //规则.1:检查是否有子节点,需清除所有子节点的选定状态; void SetNodeImg11(TreeNode tn) { foreach (TreeNode t in tn.Nodes) { t.SelectedImageIndex = 0; t.ImageIndex = 0; if (t.Nodes.Count != 0) SetNodeImg11(t); } } //设置节点选定状态: //规则.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态 void SetNodeImg12(TreeNode tn) { if (tn.Parent == null) return; int Img0Num = 0, Img1Num = 0, Img2Num = 0; //统计同级节点选中情况 foreach (TreeNode t in tn.Parent.Nodes) { switch (t.ImageIndex) { case 1: Img1Num++; break; case 2: Img2Num++; break; case 0: default: Img0Num++; break; } } //如果同级节点选中和未选中的都有 if (Img1Num != 0 || (Img0Num != 0 && Img2Num != 0)) { tn.Parent.SelectedImageIndex = 1; tn.Parent.ImageIndex = 1; } else { tn.Parent.StateImageIndex = 0; tn.Parent.ImageIndex = 0; } SetNodeImg12(tn.Parent); } //设置节点选定状态: //规则.1:检查是否有子节点,设置所有子节点为选定状态 void SetNodeImg21(TreeNode tn) { foreach (TreeNode t in tn.Nodes) { t.SelectedImageIndex = 2; t.ImageIndex = 2; if (t.Nodes.Count != 0) { SetNodeImg21(t); } } } //设置节点选定状态: //规则.2:检查是否有父节点,如有,则根据兄弟节点的选定状态修改父节点的选定状态 void SetNodeImg22(TreeNode tn) { if (tn.Parent == null) return; int Img0Num = 0, Img1Num = 0, Img2Num = 0; foreach (TreeNode t in tn.Parent.Nodes) { //if (t.ImageIndex == 0) // Img0Num++; //if (t.ImageIndex == 1) // Img1Num++; //if (t.ImageIndex == 2) // Img2Num++; switch (t.ImageIndex) { case 1: Img1Num++; break; case 2: Img2Num++; break; case 0: default: Img0Num++; break; } } if (Img1Num != 0 || (Img0Num != 0 && Img2Num != 0)) { tn.Parent.SelectedImageIndex = 1; tn.Parent.ImageIndex = 1; } //else if (Img1Num == 0 && Img2Num == 0) //{ // tn.Parent.SelectedImageIndex = 0; // tn.Parent.ImageIndex = 0; //} else { tn.Parent.StateImageIndex = 2; tn.Parent.ImageIndex = 2; } SetNodeImg22(tn.Parent); } } }