Click here to Skip to main content
15,884,472 members
Articles / Programming Languages / Visual Basic
Tip/Trick

Drag drop multiple selected rows of datagridview with left mouse button

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
2 Mar 2012CPOL 55K   6   4
Drag drop multiple selected rows of datagridview with left mouse button
If you have a multiselectable datagridview on your form, you most likely are looking for a method to process intuitive drag & drop of the selected rows to another control. But, as soon as you click onto a row (selected or not) with the mere left button any selection is gone immediately. One could think about a workaround by using the right mouse button, but again, that is not intuitive, since 99% of all dd operations are normally done by click and hold of the left button.

What to do? Of course: subclassing. I thought about it for awhile and detected the crucial point in the OnMouseDown event. Inside this event, the base class of the datagridview is doing the selection job. So we override this event and wait for the OnMouseUp event to determine, if a multiselect drag drop has been performed. In this case, we catch up the preceeding MouseDown event and everything works fine.

Since we still want the 'only one row' dd as well, I also implemented the property
AllowMultiRowDrag
.

Here is the trick:

VB.NET
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionExcellent Article - Slight change to enable cell edit Pin
JFish2226-Jan-14 16:51
JFish2226-Jan-14 16:51 
QuestionWorks until the datagridview in in a container like a tab control Pin
Mark Regal3-Apr-12 5:07
Mark Regal3-Apr-12 5:07 
QuestionIncorporating this into a custom control library Pin
nyarlathotep300121-Mar-12 19:43
nyarlathotep300121-Mar-12 19:43 
GeneralReason for my vote of 5 nice one. Pin
Nikhil_S1-Mar-12 17:53
professionalNikhil_S1-Mar-12 17:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.