treeview
TreeView右键选中节点
private void treeView1_MouseClick(object sender, MouseEventArgs e) { Point p = new Point (e.X,e.Y ); if (e.Button == MouseButtons.Right) { TreeNode tn = treeViewEx1.GetNodeAt(p); if (tn != null) { treeViewEx1.SelectedNode = tn; } }
}
(不判断右键时,左键点击空白处也能选中鼠标所在行的节点)
private void treeView1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { treeView1.SelectedNode = treeView1.GetNodeAt(e.Location); } }
TreeView点击空白
//处理鼠标Up事件 private void treeView1_MouseUp(object sender, MouseEventArgs e) { Point p = new Point(e.X, e.Y); TreeNode selectNode = treeView1.GetNodeAt(p); bool isBlank = false; if (selectNode == null) isBlank = true; else { if(selectNode.Bounds.Contains(e.X,e.Y) == false) isBlank = true; } if (isBlank) { //处理选择空白 } }
treeview按Shift选中多行
1.自带控件可用,重绘的不好使
/// <summary> /// 这个类提供树形视图的另类操作 /// </summary> //[CodeDescription("2013.07.24","封装多选的功能")] public class TreeViewAssist { #region 属性 /// <summary> /// 批量选择的节点 /// </summary> private List<TreeNode> m_selectedNodes = new List<TreeNode>(); private bool m_controlKeyDown = false; private bool m_shiftKeyDown = false; private TreeView m_treeView; private Color m_defaultForeColor = Color.Black; private Color m_defaultBackColor = Color.White; private Color m_highlightBackColor = SystemColors.Highlight; private Color m_highlightForeColor = Color.White; private bool m_enableMultiSelect = true; private bool m_enebleCascadeSelect = true; private bool m_allowParentSingleCheck = true; #endregion #region 对外属性 /// <summary> /// 获得批量选择的节点 /// <para>注意,这个是通过Shift键或者Control键得到的节点,键没用按下去就没有</para> /// </summary> public List<TreeNode> SelectedNodes { get { return m_selectedNodes; } } public Color DefaultForeColor { get { return m_defaultForeColor; } set { m_defaultForeColor = value; } } public Color DefaultBackColor { get { return m_defaultBackColor; } set { m_defaultBackColor = value; } } public Color HighlightBackColor { get { return m_highlightBackColor; } set { m_highlightBackColor = value; } } public Color HighlightForeColor { get { return m_highlightForeColor; } set { m_highlightForeColor = value; } } /// <summary> /// 是否允许多选 /// </summary> public bool EnableMultiSelect { get { return m_enableMultiSelect; } set { if (m_enableMultiSelect != value) { m_enableMultiSelect = value; SetEvent(); } } } /// <summary> /// 是否允许级联选择 /// </summary> public bool EnebleCascadeSelect { get { return m_enebleCascadeSelect; } set { if (m_enebleCascadeSelect != value) { m_enebleCascadeSelect = value; SetEvent(); } } } /// <summary> /// 是否允许父节点单独进行选择,默认true,即子类没有选择那么父类也没得选择 /// </summary> public bool AllowParentSingleCheck { get { return m_allowParentSingleCheck; } set { m_allowParentSingleCheck = value; } } #endregion #region 构造函数 /// <summary> /// 根据一个树来构建一个辅助 /// </summary> /// <param name="treeView"></param> public TreeViewAssist(TreeView treeView) : this(treeView, true, true) { } /// <summary> /// 建立图层节点的帮助 /// </summary> /// <param name="treeView"></param> /// <param name="enableMultiSelect">是否允许多点选择</param> /// <param name="enableCascadeSelect">是否允许级联选择</param> public TreeViewAssist(TreeView treeView, bool enableMultiSelect,bool enableCascadeSelect) { m_enableMultiSelect = enableMultiSelect; m_enebleCascadeSelect = enableCascadeSelect; m_treeView = treeView; m_defaultForeColor = treeView.ForeColor; m_defaultBackColor = treeView.BackColor; SetEvent(); } #endregion #region TreeView事件 /// <summary> /// 根据设置配置事件 /// </summary> private void SetEvent() { if (m_enableMultiSelect) { m_treeView.KeyDown += new KeyEventHandler(m_treeView_KeyDown); m_treeView.KeyUp += new KeyEventHandler(m_treeView_KeyUp); m_treeView.NodeMouseClick += new TreeNodeMouseClickEventHandler(m_treeView_NodeMouseClick); } else { m_treeView.KeyDown -= new KeyEventHandler(m_treeView_KeyDown); m_treeView.KeyUp -= new KeyEventHandler(m_treeView_KeyUp); m_treeView.NodeMouseClick -= new TreeNodeMouseClickEventHandler(m_treeView_NodeMouseClick); } if (m_enebleCascadeSelect) { m_treeView.AfterCheck += new TreeViewEventHandler(m_treeView_AfterCheck); } else { m_treeView.AfterCheck -= new TreeViewEventHandler(m_treeView_AfterCheck); } } void m_treeView_AfterCheck(object sender, TreeViewEventArgs e) { if (e.Action != TreeViewAction.ByMouse) return; TriggerParentCheck(e.Node, e.Node.Checked); TriggerChildCheck(e.Node, e.Node.Checked); } void m_treeView_KeyDown(object sender, KeyEventArgs e) { m_controlKeyDown = e.Control; m_shiftKeyDown = e.Shift; } void m_treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Button == MouseButtons.Left) { OnSelectingNodes(e.Node); } } void m_treeView_KeyUp(object sender, KeyEventArgs e) { m_controlKeyDown = false; m_shiftKeyDown = false; } #endregion #region 批量选择的代码 /// <summary> /// 清除选择的节点 /// </summary> public void ClearSelectedNodes() { if (m_selectedNodes.Count == 0) return; foreach (TreeNode tn in m_selectedNodes) { tn.ForeColor = DefaultForeColor; tn.BackColor = DefaultBackColor; } m_selectedNodes.Clear(); } /// <summary> /// 清除选择的节点 /// </summary> /// <param name="tn"></param> private void ClearSelectedNode(TreeNode tn) { tn.ForeColor = DefaultForeColor; tn.BackColor = DefaultBackColor; m_selectedNodes.Remove(tn); } /// <summary> /// 添加一个节点作为选择节点的一个 /// </summary> /// <param name="tn"></param> /// <param name="checkExist"></param> private void SetNodeAsSelectedNodes(TreeNode tn, bool checkExist) { if (checkExist) { if (m_selectedNodes.Contains(tn)) return; } m_selectedNodes.Add(tn); tn.BackColor = HighlightBackColor; tn.ForeColor = HighlightForeColor; } /// <summary> /// 正在通过Shift或者Control的节点 /// </summary> /// <param name="selectedNode"></param> private void OnSelectingNodes(TreeNode selectedNode) { if (m_controlKeyDown == false && m_shiftKeyDown == false) { ClearSelectedNodes(); return; } if (m_controlKeyDown) { if (m_selectedNodes.Count == 0) { if (this.m_treeView.SelectedNode != null) { SetNodeAsSelectedNodes(this.m_treeView.SelectedNode, true); } } SetNodeAsSelectedNodes(selectedNode, true); } if (m_shiftKeyDown) { TreeNode firstTn = this.m_treeView.SelectedNode; if (m_selectedNodes.Count > 0) firstTn = m_selectedNodes[0]; TreeNode secondTn = selectedNode; AddShiftNodes(firstTn, secondTn); } } /// <summary> /// 添加经过Shift控制的节点 /// </summary> /// <param name="firstTn"></param> /// <param name="secondTn"></param> private void AddShiftNodes(TreeNode firstTn, TreeNode secondTn) { TreeNode nextVisibleNode = firstTn; bool find = false; while (nextVisibleNode != null) { if (nextVisibleNode == secondTn) { find = true; break; } nextVisibleNode = nextVisibleNode.NextVisibleNode; } //清除原来的数据 ClearSelectedNodes(); if (firstTn != null && secondTn != null) { TravelShiftSelectedNodes(firstTn, secondTn, find); } } /// <summary> /// 添加Shift控制选择的节点 /// </summary> /// <param name="currentNode"></param> /// <param name="secondNode"></param> /// <param name="findNext"></param> private void TravelShiftSelectedNodes(TreeNode currentNode, TreeNode secondNode, bool findNext) { SetNodeAsSelectedNodes(currentNode, false); if (currentNode == secondNode) return; TreeNode nextNode; if (findNext) nextNode = currentNode.NextVisibleNode; else nextNode = currentNode.PrevVisibleNode; if (nextNode != null) { TravelShiftSelectedNodes(nextNode, secondNode, findNext); } } /// <summary> /// 组织选择的节点,包括 /// <para>判断一个节点的选择了,但它的子节点只选择了一部分</para> /// <para>一个节点和它的子节点都选择了,那么只选择这个节点,子节点不作为选择</para> /// </summary> /// <returns></returns> public bool OrganizeSelectedNodes() { bool[] toBeRemove = new bool[m_selectedNodes.Count]; for (int i = m_selectedNodes.Count - 1; i > -1; i--) { //存在一个组,这个组内的数据只有部分被选择 if (m_selectedNodes[i].Nodes.Count > 0) { int childSelCount = 0; foreach (TreeNode tn in m_selectedNodes[i].Nodes) { if (m_selectedNodes.Contains(tn)) { childSelCount++; } } if (childSelCount != 0 && childSelCount < m_selectedNodes[i].Nodes.Count) { MessageBox.Show("【" + m_selectedNodes[i].Text + "】只选择了部分的数据,不能进行下一步操作!"); return false; } } } for (int i = m_selectedNodes.Count - 1; i > -1; i--) { for (int j = i - 1; j > -1; j--) { if (m_selectedNodes[j].Parent == m_selectedNodes[i]) { toBeRemove[j] = true; } } } for (int i = m_selectedNodes.Count - 1; i > -1; i--) { if (toBeRemove[i]) m_selectedNodes.RemoveAt(i); } return true; } #endregion #region 级联选择 /// <summary> /// 级联到父类的选择 /// </summary> /// <param name="tn"></param> /// <param name="tnChecked"></param> public void TriggerParentCheck(TreeNode tn, bool tnChecked) { if (tnChecked) { TreeNode parentTN = tn.Parent; //传递上层 while (parentTN != null && parentTN.Checked == false) { parentTN.Checked = true; parentTN = parentTN.Parent; } } else { TreeNode parentTN = tn.Parent; if (parentTN == null) return; bool childHasChecked = false; for (int i = 0; i < parentTN.Nodes.Count; i++) { if (parentTN.Nodes[i].Checked) { childHasChecked = true; break; } } if (childHasChecked) { TriggerParentCheck(tn, true); } else if (m_allowParentSingleCheck == false) { if (parentTN.Checked == true) { parentTN.Checked = false; TriggerParentCheck(parentTN, false); } } } } /// <summary> /// 级联到子类的选择 /// </summary> /// <param name="tn"></param> /// <param name="tnChecked"></param> public void TriggerChildCheck(TreeNode tn, bool tnChecked) { TriggerChildCheck(tn, tnChecked, true); } /// <summary> /// 级联到子类的选择 /// </summary> /// <param name="tn"></param> /// <param name="tnChecked"></param> /// <param name="checkNodeCount"></param> private void TriggerChildCheck(TreeNode tn, bool tnChecked, bool checkNodeCount) { if (checkNodeCount) { if (tn.Nodes == null && tn.Nodes.Count == 0) { return; } } foreach (TreeNode childTN in tn.Nodes) { if (childTN.Checked != tnChecked) { childTN.Checked = tnChecked; if (childTN.Nodes != null && childTN.Nodes.Count != 0) { TriggerChildCheck(childTN, tnChecked, false); } } } } #endregion #region 卸载 /// <summary> /// 卸载 /// </summary> public void Dispose() { EnableMultiSelect = false; this.EnebleCascadeSelect = false; } #endregion }
private void Form1_Load(object sender, EventArgs e) { TreeViewAssist tv = new TreeViewAssist(treeView1 ); tv.EnableMultiSelect = true; tv.EnebleCascadeSelect = true; }