65.9K
CodeProject 正在变化。 阅读更多。
Home

使用左键拖放数据网格视图中的多个选定行

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2012年3月1日

CPOL
viewsIcon

56605

使用左键拖放数据网格视图中的多个选定行

如果在你的窗体上有一个可多选的数据网格视图,你可能正在寻找一种方法来处理将选定的行直观地拖放到另一个控件的操作。但是,一旦你用左键点击任何一行(无论是否已选中),任何选择都会立即消失。可以考虑使用右键按钮作为一种解决方法,但同样,这并不直观,因为 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
© . All rights reserved.