ドラッグアンドドロップでTreeNodeを移動する 最終更新日 2004年12月19日 0:00 TreeViewにドラッグアンドドロップ関連の処理を書き加えることで、TreeView内に表示されているTreeNodeをドラッグアンドドロップで移動できるように拡張したTreeViewクラスを紹介する。 このコードでは、ドロップ先のノードとドラッグされているノードの親子関係をチェックし、ドロップできるか否かを判定している。 別ウィンドウで開く すべて選択してコピー ダウンロード 行番号を表示する Public Class DragDropTreeView Inherits TreeView ''' <summary> ''' ドラッグアンドドロップされるノードのデータ ''' </summary> Private Structure DragDropNodeData Public Sub New(ByVal node As TreeNode) m_Node = node End Sub Private m_Node As TreeNode Public ReadOnly Property Node() As TreeNode Get Return m_Node End Get End Property End Structure ''' <summary> ''' ''' </summary> Public Sub New() MyBase.New() Me.AllowDrop = True End Sub ' ドラッグアンドドロップの開始点 Private mouseDownPoint As Point ' ドラッグするノード Private dragDropNode As TreeNode ''' <summary> ''' MouseDown ''' </summary> Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs) If (e.Button And MouseButtons.Left) = MouseButtons.Left Then ' ドラッグアンドドロップの開始点 mouseDownPoint = New Point(e.X, e.Y) dragDropNode = Me.GetNodeAt(mouseDownPoint) Else mouseDownPoint = Point.Empty dragDropNode = Nothing End If MyBase.OnMouseDown(e) End Sub ''' <summary> ''' MouseUp ''' </summary> Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs) mouseDownPoint = Point.Empty MyBase.OnMouseUp(e) End Sub ''' <summary> ''' MouseMove ''' </summary> Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs) If (e.Button And MouseButtons.Left) = MouseButtons.Left Then ' ドラッグアンドドロップの範囲にあるか否かをチェックする Dim dragBound As Rectangle = New Rectangle(e.X - SystemInformation.DragSize.Width \ 2, e.Y - SystemInformation.DragSize.Height \ 2, SystemInformation.DragSize.Width, SystemInformation.DragSize.Height) If Not dragBound.Contains(mouseDownPoint) AndAlso Not dragDropNode Is Nothing Then ' ドラッグアンドドロップ用のデータを作成 Dim nodeData As New DragDropNodeData(dragDropNode) ' ノードをドラッグアンドドロップする Me.DoDragDrop(nodeData, DragDropEffects.Move) End If End If MyBase.OnMouseMove(e) End Sub ''' <summary> ''' DragEnter ''' </summary> Protected Overrides Sub OnDragEnter(ByVal drgevent As DragEventArgs) If drgevent.Data.GetDataPresent(GetType(DragDropNodeData)) Then drgevent.Effect = DragDropEffects.Move Else drgevent.Effect = DragDropEffects.None End If MyBase.OnDragEnter(drgevent) End Sub ''' <summary> ''' DragDrop ''' </summary> Protected Overrides Sub OnDragDrop(ByVal drgevent As DragEventArgs) If drgevent.Data.GetDataPresent(GetType(DragDropNodeData)) Then ' 入れ替え先のインデックス Dim targetNode As TreeNode = Me.GetNodeAt(Me.PointToClient(New Point(drgevent.X, drgevent.Y))) If Not targetNode Is Nothing Then ' ドラッグアンドドロップするアイテムのデータを取得 Dim nodeData As DragDropNodeData = DirectCast(drgevent.Data.GetData(GetType(DragDropNodeData)), DragDropNodeData) ' 移動対象を含むノード一覧を取得 Dim parentNodes As TreeNodeCollection If targetNode.Parent Is Nothing Then parentNodes = Me.Nodes Else parentNodes = targetNode.Parent.Nodes End If ' ノードのインデックスを取得 Dim targetNodeIndex As Integer = parentNodes.IndexOf(targetNode) ' 一度削除する Me.Nodes.Remove(nodeData.Node) ' 目的の場所に挿入 parentNodes.Insert(targetNodeIndex, nodeData.Node) ' 選択されているノードを設定 Me.SelectedNode = nodeData.Node End If End If MyBase.OnDragDrop(drgevent) End Sub End Class