首页 > 技术文章 > treeview

code1992 2018-09-30 14:29 原文

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
    }
View Code
 private void Form1_Load(object sender, EventArgs e)
        {
            TreeViewAssist tv = new TreeViewAssist(treeView1 );
            tv.EnableMultiSelect = true;
            tv.EnebleCascadeSelect = true;
        }
用法

 

推荐阅读