讓C# treeView 支援多選範例(非checkbox)[建置類別] 『GOOGLE 搜尋 c# treeview MultiSelect』

讓C# treeView 支援多選範例(非checkbox)[建置類別] 『GOOGLE 搜尋 c# treeview MultiSelect』

讓C# treeView 支援多選範例(非checkbox)[建置類別] 『GOOGLE 搜尋 c# treeview MultiSelect』

資料來源:https://www.codeproject.com/Articles/2756/CTreeViewwithmultipleselection

因為在公司需要C# treeView同時具備兩種以上多選功能,因此找了一下,以下是該專案核心程式碼

 

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

namespace TreeViewMS
{
    /// <summary>
    /// Summary description for TreeViewMS.
    /// </summary>
    public class TreeViewMS : System.Windows.Forms.TreeView
    {
        protected ArrayList        m_coll;
        protected TreeNode        m_lastNode, m_firstNode;

        public TreeViewMS()
        {
            m_coll = new ArrayList();
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            // TODO: Add custom paint code here

            // Calling the base class OnPaint
            base.OnPaint(pe);
        }

        public ArrayList SelectedNodes
        {
            get
            {
                return m_coll;
            }
            set
            {
                removePaintFromNodes();
                m_coll.Clear();
                m_coll = value;
                paintSelectedNodes();
            }
        }

// Triggers
//
// (overriden method, and base class called to ensure events are triggered)

        protected override void OnBeforeSelect(TreeViewCancelEventArgs e)
        {
            base.OnBeforeSelect(e);
                
            bool bControl = (ModifierKeys==Keys.Control);
            bool bShift = (ModifierKeys==Keys.Shift);

            // selecting twice the node while pressing CTRL ?
            if (bControl && m_coll.Contains( e.Node ) )
            {
                // unselect it (let framework know we don’t want selection this time)
                e.Cancel = true;
    
                // update nodes
                removePaintFromNodes();
                m_coll.Remove( e.Node );
                paintSelectedNodes();
                return;
            }

            m_lastNode = e.Node;
            if (!bShift) m_firstNode = e.Node; // store begin of shift sequence
        }

        protected override void OnAfterSelect(TreeViewEventArgs e)
        {
            base.OnAfterSelect(e);

            bool bControl = (ModifierKeys==Keys.Control);
            bool bShift = (ModifierKeys==Keys.Shift);

            if (bControl)
            {
                if ( !m_coll.Contains( e.Node ) ) // new node ?
                {
                    m_coll.Add( e.Node );
                }
                else  // not new, remove it from the collection
                {
                    removePaintFromNodes();
                    m_coll.Remove( e.Node );
                }
                paintSelectedNodes();
            }
            else 
            {
                // SHIFT is pressed
                if (bShift)
                {
                    Queue myQueue = new Queue();
                    
                    TreeNode uppernode = m_firstNode;
                    TreeNode bottomnode = e.Node;
                    // case 1 : begin and end nodes are parent
                    bool bParent = isParent(m_firstNode, e.Node); // is m_firstNode parent (direct or not) of e.Node
                    if (!bParent)
                    {
                        bParent = isParent(bottomnode, uppernode);
                        if (bParent) // swap nodes
                        {
                            TreeNode t = uppernode;
                            uppernode = bottomnode;
                            bottomnode = t;
                        }
                    }
                    if (bParent)
                    {
                        TreeNode n = bottomnode;
                        while ( n != uppernode.Parent)
                        {
                            if ( !m_coll.Contains( n ) ) // new node ?
                                myQueue.Enqueue( n );

                            n = n.Parent;
                        }
                    }
                        // case 2 : nor the begin nor the end node are descendant one another
                    else
                    {
                        if ( (uppernode.Parent==null && bottomnode.Parent==null) || (uppernode.Parent!=null && uppernode.Parent.Nodes.Contains( bottomnode )) ) // are they siblings ?
                        {
                            int nIndexUpper = uppernode.Index;
                            int nIndexBottom = bottomnode.Index;
                            if (nIndexBottom < nIndexUpper) // reversed?
                            {
                                TreeNode t = uppernode;
                                uppernode = bottomnode;
                                bottomnode = t;
                                nIndexUpper = uppernode.Index;
                                nIndexBottom = bottomnode.Index;
                            }

                            TreeNode n = uppernode;
                            while (nIndexUpper <= nIndexBottom)
                            {
                                if ( !m_coll.Contains( n ) ) // new node ?
                                    myQueue.Enqueue( n );
                                
                                n = n.NextNode;

                                nIndexUpper++;
                            } // end while
                            
                        }
                        else
                        {
                            if ( !m_coll.Contains( uppernode ) ) myQueue.Enqueue( uppernode );
                            if ( !m_coll.Contains( bottomnode ) ) myQueue.Enqueue( bottomnode );
                        }
                    }

                    m_coll.AddRange( myQueue );

                    paintSelectedNodes();
                    m_firstNode = e.Node; // let us chain several SHIFTs if we like it
                } // end if m_bShift
                else
                {
                    // in the case of a simple click, just add this item
                    if (m_coll!=null && m_coll.Count>0)
                    {
                        removePaintFromNodes();
                        m_coll.Clear();
                    }
                    m_coll.Add( e.Node );
                }
            }
        }

// Helpers
//
//

        protected bool isParent(TreeNode parentNode, TreeNode childNode)
        {
            if (parentNode==childNode)
                return true;

            TreeNode n = childNode;
            bool bFound = false;
            while (!bFound && n!=null)
            {
                n = n.Parent;
                bFound = (n == parentNode);
            }
            return bFound;
        }

        protected void paintSelectedNodes()
        {
            foreach ( TreeNode n in m_coll )
            {
                n.BackColor = SystemColors.Highlight;
                n.ForeColor = SystemColors.HighlightText;
            }
        }

        protected void removePaintFromNodes()
        {
            if (m_coll.Count==0) return;

            TreeNode n0 = (TreeNode) m_coll[0];
            Color back = n0.TreeView.BackColor;
            Color fore = n0.TreeView.ForeColor;

            foreach ( TreeNode n in m_coll )
            {
                n.BackColor = back;
                n.ForeColor = fore;
            }

        }

    }
}

 

 

 

 

 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *