Public Class MultiSelectTreeView
Inherits Windows.Forms.TreeView
Public Declare Function GetKeyState Lib "user32" Alias "GetKeyState" (ByVal nVirtKey As Integer) As Integer
Private Const VK_CONTROL As Integer = &H11
Private Const VK_SHIFT As Integer = &H10
Private m_MutliSelect As Boolean
Private m_SelBackColor As Color
Private m_SelNodes As ArrayList
Private m_AlterKeyStatus As AlterKeyStatus
Private m_ndPerSelect As TreeNode
Public Property MutliSelect() As Boolean
Get
Return Me.m_MutliSelect
End Get
Set(ByVal Value As Boolean)
Me.m_MutliSelect = Value
End Set
End Property
Public Property SelectedBackColor() As Color
Get
Return Me.m_SelBackColor
End Get
Set(ByVal Value As Color)
Me.m_SelBackColor = Value
End Set
End Property
Public ReadOnly Property SelectedNodes() As TreeNode()
Get
Return Me.m_SelNodes.ToArray(GetType(TreeNode))
End Get
End Property
Public Sub New()
MyBase.New()
Me.m_MutliSelect = True
Me.m_SelBackColor = Color.SkyBlue
Me.m_SelNodes = New ArrayList
End Sub
Private Sub FillSelectedNode(ByVal nd As TreeNode)
Dim _nd As TreeNode
Me.m_SelNodes.Clear()
If (Not Me.m_ndPerSelect Is Nothing) AndAlso (Not Me.m_ndPerSelect Is nd) AndAlso (Me.m_ndPerSelect.Parent Is nd.Parent) Then
Me.ClearSelectStyle(Me.Nodes(0))
If nd.Index > Me.m_ndPerSelect.Index Then
Me.m_SelNodes.Add(Me.m_ndPerSelect)
_nd = Me.m_ndPerSelect.NextVisibleNode
While Not _nd Is Nothing AndAlso Not _nd Is nd
Me.m_SelNodes.Add(_nd)
_nd = _nd.NextVisibleNode
End While
Me.m_SelNodes.Add(nd)
Else
Me.m_SelNodes.Add(nd)
_nd = nd.NextVisibleNode
While Not _nd Is Nothing AndAlso Not Me.m_ndPerSelect Is nd
Me.m_SelNodes.Add(_nd)
_nd = _nd.NextVisibleNode
End While
Me.m_SelNodes.Add(Me.m_ndPerSelect)
End If
For Each _nd In Me.m_SelNodes
_nd.BackColor = Me.m_SelBackColor
Next
Else
Me.m_SelNodes.Add(nd)
End If
End Sub
Private Sub ClearSelectStyle(ByVal nd As TreeNode)
Dim _nd As TreeNode
nd.BackColor = Color.Empty
For Each _nd In nd.Nodes
Me.ClearSelectStyle(_nd)
Next
End Sub
Private Sub RemoveSelectNode(ByVal nd As TreeNode)
If Me.m_SelNodes.Contains(nd) = True Then
Me.m_SelNodes.Remove(nd)
nd.BackColor = (New TreeNode).BackColor
End If
End Sub
Private Sub AppendSelectedNode(ByVal nd As TreeNode)
Dim _nd As TreeNode
Dim blnExist As Boolean = False
For Each _nd In Me.m_SelNodes
If nd Is _nd Then
Me.RemoveSelectNode(nd)
blnExist = True
Exit For
End If
Next
If blnExist = False Then
Me.m_SelNodes.Add(nd)
For Each _nd In Me.m_SelNodes
'If Not _nd.BackColor.Equals(Me.m_SelBackColor) = False Then
_nd.BackColor = Me.m_SelBackColor
'End If
Next
End If
End Sub
Private Function GetAlterKeyStatus() As AlterKeyStatus
Dim ret As AlterKeyStatus
If Math.Abs(GetKeyState(VK_CONTROL)) >= 2 ^ 6 Then
ret = AlterKeyStatus.Ctrl
ElseIf Math.Abs(GetKeyState(VK_SHIFT)) >= 2 ^ 6 Then
ret = AlterKeyStatus.Shift
Else
ret = AlterKeyStatus.None
End If
Return ret
End Function
Protected Overrides Sub OnAfterSelect(ByVal e As System.Windows.Forms.TreeViewEventArgs)
MyBase.OnAfterSelect(e)
If Not Me.SelectedNode Is Nothing Then
Select Case GetAlterKeyStatus()
Case AlterKeyStatus.Ctrl
Me.AppendSelectedNode(Me.SelectedNode)
'Case AlterKeyStatus.Shift
' Me.FillSelectedNode(Me.SelectedNode)
Case Else
Me.ClearSelectStyle(Me.Nodes(0))
Me.m_SelNodes.Clear()
Me.m_SelNodes.Add(Me.SelectedNode)
End Select
End If
Me.m_ndPerSelect = e.Node
End Sub
Public Sub ClearSelectedNodes()
Me.ClearSelectStyle(Me.Nodes(0))
Me.m_SelNodes.Clear()
End Sub