使用左键拖放数据网格视图中的多个选定行
使用左键拖放数据网格视图中的多个选定行
如果在你的窗体上有一个可多选的数据网格视图,你可能正在寻找一种方法来处理将选定的行直观地拖放到另一个控件的操作。但是,一旦你用左键点击任何一行(无论是否已选中),任何选择都会立即消失。可以考虑使用右键按钮作为一种解决方法,但同样,这并不直观,因为 99% 的拖放操作通常是通过点击并按住左键完成的。该怎么办?当然:子类化。我思考了一段时间,并在 OnMouseDown 事件中发现了关键点。在这个事件中,数据网格视图的基类正在执行选择操作。因此,我们重写这个事件,并等待 OnMouseUp 事件来确定是否执行了多选拖放。在这种情况下,我们捕获之前的 MouseDown 事件,一切就正常工作了。由于我们仍然希望支持“单行拖放”,我也实现了属性
AllowMultiRowDrag。这里是技巧
Public Class DD_DataGridView
Inherits DataGridView
Public Property AllowMultiRowDrag As Boolean = False
Private dragBoxFromMouseDown As Rectangle
Private rowIndexFromMouseDown As Int32
Private lastLeftMouseDownArgs As MouseEventArgs
Protected Overrides Sub OnMouseDown(e As System.Windows.Forms.MouseEventArgs)
If (e.Button And Windows.Forms.MouseButtons.Left) = Windows.Forms.MouseButtons.Left Then
rowIndexFromMouseDown = Me.HitTest(e.X, e.Y).RowIndex
If rowIndexFromMouseDown <> -1 Then
Dim dragSize As Size = SystemInformation.DragSize
dragBoxFromMouseDown = New Rectangle(New Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize)
lastLeftMouseDownArgs = e 'remember the MouseEventArgs
If AllowMultiRowDrag Then
Exit Sub 'Don't call the base function here to keep the selection
End If
Else
dragBoxFromMouseDown = Rectangle.Empty
lastLeftMouseDownArgs = Nothing
End If
End If
MyBase.OnMouseDown(e) 'in all other cases call the base function
End Sub
Protected Overrides Sub OnMouseUp(e As System.Windows.Forms.MouseEventArgs)
If lastLeftMouseDownArgs IsNot Nothing AndAlso (e.Button And Windows.Forms.MouseButtons.Left) = Windows.Forms.MouseButtons.Left Then
'there has been a multiselect drag operation so catch up the MouseDown event
If AllowMultiRowDrag Then MyBase.OnMouseDown(lastLeftMouseDownArgs)
End If
MyBase.OnMouseUp(e)'now call the base Up-function
End Sub
Protected Overrides Sub OnMouseMove(e As System.Windows.Forms.MouseEventArgs)
If lastLeftMouseDownArgs IsNot Nothing AndAlso (e.Button And Windows.Forms.MouseButtons.Left) = Windows.Forms.MouseButtons.Left Then
If (dragBoxFromMouseDown <> Rectangle.Empty) AndAlso (Not dragBoxFromMouseDown.Contains(e.X, e.Y)) Then
'we want to drag one/multiple rows
Dim row As DataGridViewRow = Me.Rows(rowIndexFromMouseDown)
row.Selected = True 'always select the row that was under the mouse in the OnMouseDown event.
If Me.AllowMultiRowDrag Then
'multiselect drag, so make all selected rows the drag data
Dim dropEffect As DragDropEffects = Me.DoDragDrop(Me.SelectedRows, DragDropEffects.Move)
Else
'only one row to drag
Dim dropEffect As DragDropEffects = Me.DoDragDrop(row, DragDropEffects.Move)
End If
End If
End If
MyBase.OnMouseMove(e) 'let's do the base class the rest
End Sub
End Class