liu5320102 发表于 2013-2-7 03:51:33

Treeview多选

最近客户提出一个需求,无法忍受通过checkbox来实现treeview多选.而必须改用统一的 ctrl,shift.

参照了csdn上的几篇文章后,实现了这样的treeview.

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Text;

namespace MyTreeview
{   
    public delegate void TreeNodeChangedHandle(object sender, EventArgs args);

    ///   <summary>
    ///   MultiSelectTreeView design by terro
    ///   </summary>
   
    public class MultiSelectTreeView : TreeView
    {
      
      public event TreeNodeChangedHandle TreeNodeChanged;

      private ArrayList selectedNodes = new ArrayList();
      private bool isMulSelect = false;
      private TreeNode CurrentNode = null;

      public MultiSelectTreeView()
      {
         
      }

      public virtual void Initialize()
      {
            this.Sorted = false;
            this.ShowRootLines = false;
            this.Indent = 15;
            this.ItemHeight = 18;         
      }

      ///   <summary>
      ///    Get currnent node,readonly.don't use the SelectNode to get the select node
      ///   </summary>
      public TreeNode CurrentNode
      {
            get
            {
                return currentNode;
            }
      }

      ///   <summary>
      ///   Get all the select nodes
      ///   </summary>
      public ArrayList SelectedNodes
      {
            get
            {
                return selectedNodes;
            }
      }

      ///   <summary>
      ///   if the control allow mulselct
      ///   </summary>
      public bool IsMulSelect
      {
            get
            {
                return isMulSelect;
            }
            set
            {
                isMulSelect = value;
            }
      }

      ///   <summary>
      ///   onclick
      ///   </summary>
      ///   <param   name="e"></param>
      protected override void OnMouseClick(MouseEventArgs e)   

      {         
            TreeNode node = GetNodeAt(e.X, e.Y);         
            if (node != null)
            {
                if (isMulSelect)
                {
                  if (!(selectedNodes.Count == 1 && selectedNodes == node))
                  {
                        if ((Control.ModifierKeys & Keys.Control) != 0 || e.Button == MouseButtons.Right)
                            MulSelectNode(node, e.Button == MouseButtons.Right);
                        else if ((Control.ModifierKeys & Keys.Shift) != 0)
                            ShiftMulSelectNode(node, e.Button == MouseButtons.Right);
                        else
                            SingleSelectNode(node);
                  }
                }
                else
                  SetCurrentNode(node);
            }
      }

      ///   <summary>
      ///   excuse when after clicking
      ///   </summary>
      ///   <param   name="e"></param>
      protected override void OnAfterSelect(TreeViewEventArgs e)
      {
            SetCurrentNode(e.Node);         
            base.OnAfterCheck(e);
      }

      ///   <summary>
      ///   MulSelect
      ///   </summary>
      ///   <param   name="node"></param>
      ///   <param   name="mustSelect"></param>
      private void MulSelectNode(TreeNode node, bool mustSelect)
      {
            if (selectedNodes.Contains(node) && !mustSelect)
            {
                selectedNodes.Remove(node);
                LowlightNode(node);
                SetCurrentNode((TreeNode)selectedNodes);
            }
            else if(!mustSelect)
            {               
                selectedNodes.Add(node);
                HighlightNode(node);
                SetCurrentNode(node);
            }
      }

      /// <summary>
      /// ShiftMulSelectNode
      /// </summary>
      /// <param name="node"></param>
      /// <param name="mustSelec"></param>
      private void ShiftMulSelectNode(TreeNode node, bool mustSelect)
      {         
            if (selectedNodes.Contains(node) && !mustSelect)
            {
                selectedNodes.Remove(node);
                LowlightNode(node);
                SetCurrentNode((TreeNode)selectedNodes);
            }
            else if (node.Parent == currentNode.Parent && !mustSelect)
            {
                TreeNode addNode = node;
                for (int i = System.Math.Abs(currentNode.Index - node.Index); i > 0; i--)
                {
                  if (!selectedNodes.Contains((object)addNode))
                  {
                        selectedNodes.Add(addNode);
                        HighlightNode(addNode);
                  }

                  addNode = currentNode.Index > node.Index ? addNode.NextNode : addNode.PrevNode;                  
                }               

                SetCurrentNode(node);
            }
      }

      ///   <summary>
      ///   single select
      ///   </summary>
      ///   <param   name="node"></param>
      private void SingleSelectNode(TreeNode node)
      {
            foreach (TreeNode nd in SelectedNodes)
            {
                nd.BackColor = BackColor;
                nd.ForeColor = ForeColor;
            }
            SelectedNodes.Clear();
            SelectedNodes.Add(node);
            HighlightNode(node);
            SetCurrentNode(node);
      }

      ///   <summary>
      ///   Set current node
      ///   </summary>
      ///   <param   name="node"></param>
      private void SetCurrentNode(TreeNode node)
      {
            if (isMulSelect)
                SelectedNode = null;
            if (currentNode != node)
            {
                currentNode = node as TreeNode;
                if (TreeNodeChanged != null)
                  TreeNodeChanged(currentNode, EventArgs.Empty);            
            }
      }   

      ///   <summary>
      ///   cancel the light
      ///   </summary>
      ///   <param   name="node"></param>
      private void LowlightNode(TreeNode node)
      {
            node.BackColor = BackColor;
            node.ForeColor = SystemColors.ControlText;
      }

      ///   <summary>
      ///   set the light
      ///   </summary>
      ///   <param   name="node"></param>
      private void HighlightNode(TreeNode node)
      {
            node.BackColor = SystemColors.Highlight;
            node.ForeColor = SystemColors.HighlightText;
      }

    }
}

在用shift选择不同父树的子树时,第一次选择会被屏蔽,因为这样不能获取到树的结构关系.
页: [1]
查看完整版本: Treeview多选