ドラッグアンドドロップでListBoxのアイテムを移動する 最終更新日 2004年12月19日 0:00 ListBoxにドラッグアンドドロップ関連の処理を書き加えることで、ListBox内に表示されているアイテムをドラッグアンドドロップで移動できるように拡張したListBoxクラスを紹介する。 別ウィンドウで開く すべて選択してコピー ダウンロード 行番号を表示する Public Class DragDropListBox Inherits ListBox ''' <summary> ''' ドラッグアンドドロップされるアイテムのデータ ''' </summary> Private Structure DragDropItemData Public Sub New(ByVal index As Integer) m_Index = index End Sub Private m_Index As Integer Public ReadOnly Property Index() As Integer Get Return m_Index End Get End Property End Structure ''' <summary> ''' ''' </summary> Public Sub New() MyBase.New() Me.AllowDrop = True End Sub ' ドラッグアンドドロップの開始点 Private mouseDownPoint As Point ' ドラッグするアイテムのインデックス Private dragDropSourceItemIndex As Integer ''' <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) dragDropSourceItemIndex = Me.IndexFromPoint(e.X, e.Y) Else mouseDownPoint = Point.Empty dragDropSourceItemIndex = ListBox.NoMatches 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 dragDropSourceItemIndex <> ListBox.NoMatches Then ' ドラッグアンドドロップ用のデータを作成 Dim itemData As DragDropItemData = New DragDropItemData(dragDropSourceItemIndex) ' アイテムをドラッグアンドドロップする Dim effects As DragDropEffects = Me.DoDragDrop(itemData, 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(DragDropItemData)) 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(DragDropItemData)) Then ' 入れ替え先のインデックス Dim targetIndex As Integer = Me.IndexFromPoint(Me.PointToClient(New Point(drgevent.X, drgevent.Y))) If targetIndex = ListBox.NoMatches Then targetIndex = Me.Items.Count - 1 ' ドラッグアンドドロップするアイテムのデータを取得 Dim itemData As DragDropItemData = DirectCast(drgevent.Data.GetData(GetType(DragDropItemData)), DragDropItemData) ' アイテムを入れかえる Dim temp As Object = Me.Items(itemData.Index) Me.Items(itemData.Index) = Me.Items(targetIndex) Me.Items(targetIndex) = temp ' 入れ替えたアイテムを選択する Me.SelectedItem = temp End If MyBase.OnDragDrop(drgevent) End Sub End Class