Hi,
I have a DGV (dgvListOfJobs), populated from an SQL database to show the user a list of 'jobs' (i.e. rows). I also show 7 other DGV's (dgvMonday, dgvTuesday, etc) for each day of the week so the user can drag a job from the list and drop it onto a particular day. Once dropped I update the SQL record with a corresponding date. The user can also drag and drop between days, or drag a job back to the main job list to remove it from the week's jobs (i.e. the SQL writes a null to the date field). This all works fine.
However - if a user picks up a job and drops it onto the same dgv, it still triggers the 'dropped' event and writes a date, or a null, to the SQL. I want to have a check at the start of the 'drop' procedure so if the job was picked up and dropped back into the same DGV, the drop event quits straight away without re-writing the SQL.

I could read the SQL to see if the date matched but this involves an EXTRA sql access and I am trying to speed up the process by removing an SQL event if at all possible.

After Googling for a solution I think it may be something to do with 'DirectCast' but I can only get this to report 'DataGridView' as the source, not the name of a specific dgv - 'dgvThursday' for example.

I notice the 'DragDrop' event paramters include a 'sender' object but cannot work out how to utilise this (and even if it will help!)

Dani AI

Generated

Short answer: sender in a DragDrop handler is the drop target (the control that raised the event), so DirectCast(sender, DataGridView) will always show whichever grid the handler is attached to — which is why saw dgvListOfJobs every time. As showed, a mouse-down flag works. A more robust, scalable approach is to embed the source identifier (or the job primary key) into the drag data when you call DoDragDrop, then check that value in the DragDrop handler and exit immediately if the source equals the target.

Example (embed source name + job id into the DataObject):

' when starting the drag (CellMouseDown/CellMouseMove)
Dim data As New DataObject()
data.SetData(DataFormats.Text, jobText)
data.SetData("SourceGrid", CType(sender, DataGridView).Name)
data.SetData("JobID", jobPrimaryKey)    ' integer or string
CType(sender, DataGridView).DoDragDrop(data, DragDropEffects.Move)

Then in a shared DragDrop handler (attached to all day grids and the main list) do an early exit:

Private Sub AnyGrid_DragDrop(sender As Object, e As DragEventArgs) _
    Handles dgvListOfJobs.DragDrop, dgvMonday.DragDrop, dgvTuesday.DragDrop
    Dim target As DataGridView = DirectCast(sender, DataGridView)
    Dim srcName As String = TryCast(e.Data.GetData("SourceGrid"), String)
    If srcName IsNot Nothing AndAlso srcName = target.Name Then Exit Sub
    Dim jobId = e.Data.GetData("JobID")
    ' Compare job's current assigned date (from in-memory row) with target date;
    ' only issue the SQL UPDATE if the date actually needs changing.
End Sub

Notes and cautions: passing the grid name or job primary key is safer than passing a direct control reference (avoid serialisation/IPC issues). Ensure AllowDrop = True and that DragEnter/DragOver set e.Effect appropriately. The flag method suggested is simpler for a few grids; carrying source info in the DataObject scales better and avoids global state while making the early-exit check trivial.

Recommended Answers

All 4 Replies

dim dgv as datagridview = DirectCast(sender,DatagridView)
if dgv.name = "..." then

Thanks xrj - sorry about the delay replying. i have put this code into the 'Handles dgvListOfJobs.DragDrop'

        Dim mySourceDGV As DataGridView = DirectCast(sender, DataGridView)
        MessageBox.Show("Source = " & mySourceDGV.Name.ToString)

However the messagebox only ever shows 'dgvListOfJobs' as the source, even if I have dragged and dropped a job from 'Monday' for example. Do I need to set something up in the initial 'MouseDown' event ie. when I initially pick up the job?

On the mouse down event for each source, while initiating the drag, you may set a flag IsMouseDown with a value indicating which is the source. If the mouse down event occurs in let's say DataGridView1, then set IsMouseDown=srcIsNum1. In case the dragging starts with a mouse down event on a cell (or row, column, ...) of DataGridView2, set IsMouseDown=srcIsNum2. Of course flag IsMouseDown can be a class instance and contain much more information; not only the source, but the row, column, or any required data.

    Enum mouseDwn
        srcIsNum1
        srcIsNum2
    End Enum
    Dim IsMouseDown As mouseDwn

For example:

    Enum mouseDwn
        none = 0
        srcIsNum1
        srcIsNum2
    End Enum
    Dim IsMouseDown As mouseDwn = mouseDwn.none
    Private Sub DataGridView1_CellMouseDown(sender As Object, e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDown
        IsMouseDown = mouseDwn.srcIsNum1
    End Sub
    Private Sub DataGridView2_CellMouseDown(sender As Object, e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DataGridView2.CellMouseDown
        IsMouseDown = mouseDwn.srcIsNum2
    End Sub
    Private Sub DataGridView2_CellMouseMove(sender As Object, e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DataGridView2.CellMouseMove
        If IsMouseDown = mouseDwn.srcIsNum2 Then
            With DataGridView2
                .DoDragDrop(CStr(.Rows(e.RowIndex).Cells(e.ColumnIndex).Value), DragDropEffects.Copy)
                IsMouseDown = mouseDwn.none
            End With
        End If
    End Sub
    Private Sub DataGridView1_CellMouseMove(sender As Object, e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseMove
        If IsMouseDown = mouseDwn.srcIsNum1 Then
            With DataGridView1
                .DoDragDrop(CStr(.Rows(e.RowIndex).Cells(e.ColumnIndex).Value), DragDropEffects.Copy)
                IsMouseDown = mouseDwn.none
            End With
        End If
    End Sub
    Private Sub DataGridView1_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragEnter
        If e.Data.GetDataPresent(DataFormats.Text) AndAlso _
        IsMouseDown = mouseDwn.srcIsNum2 Then
            e.Effect = DragDropEffects.Copy
        Else
            e.Effect = DragDropEffects.None
        End If
    End Sub
    Private Sub DataGridView2_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles DataGridView2.DragEnter
        If e.Data.GetDataPresent(DataFormats.Text) AndAlso _
        IsMouseDown = mouseDwn.srcIsNum1 Then
            e.Effect = DragDropEffects.Copy
        Else
            e.Effect = DragDropEffects.None
        End If
    End Sub
    Private Sub DataGridView1_DragDrop(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragDrop
        Try
            Dim row, col As Integer
            getRowAndColumn(sender, row, col, e)
            DataGridView1.Rows(row).Cells(col).Value = e.Data.GetData(DataFormats.Text)
        Catch ex As Exception
        End Try
    End Sub
    Private Sub DataGridView2_DragDrop(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles DataGridView2.DragDrop
        Try
            Dim row, col As Integer
            getRowAndColumn(sender, row, col, e)
            DataGridView2.Rows(row).Cells(col).Value = e.Data.GetData(DataFormats.Text)
        Catch ex As Exception
        End Try
    End Sub
    Sub getRowAndColumn(sender As Object, ByRef row As Int32, ByRef col As Int32, e As System.Windows.Forms.DragEventArgs)
        With DataGridView1
            Dim grvScreenLocation As Point = sender.PointToScreen(sender.Location)
            Dim tempX As Integer = DataGridView.MousePosition.X - grvScreenLocation.X + sender.Left
            Dim tempY As Integer = DataGridView.MousePosition.Y - grvScreenLocation.Y + sender.Top
            Dim hit As DataGridView.HitTestInfo = sender.HitTest(tempX, tempY)
            row = hit.RowIndex
            col = hit.ColumnIndex
            .Rows(row).Cells(col).Value = e.Data.GetData(DataFormats.Text)
        End With
    End Sub
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.