Question

I'm implementing drag and drop functionality between two datagridviews. This works as intended with one exception: it is possible to drag and drop within the same datagridview. This results in duplicated rows. I want to limit the functionality so that I can only drag from one datagridview to another. Does anyone know how this can be achieved? I'm guessing some kind of hit test is required but I'm not sure how to implement this...

The code I am using is as follows:

Private Sub dgvFMAvailable_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles dgvFMAvailable.MouseMove

    If e.Button = Windows.Forms.MouseButtons.Left Then
        Me.dgvFMAvailable.DoDragDrop(Me.dgvFMAvailable.SelectedRows, DragDropEffects.Move)
    End If

End Sub

and

Private Sub dgvFMSelected_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles dgvFMSelected.DragDrop

    Try
        Me.SelectFM(CType(e.Data.GetData(GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection))

    Finally
        e.Effect = DragDropEffects.None
    End Try

End Sub
Was it helpful?

Solution

Just a quick idea. What if when you start the drag you hold the name of the origin grid. When you do the drop check the name, if they are the same object then don't allow the drop.

OTHER TIPS

Simply test for reference equality when dropping. Something like this:

If Object.ReferenceEquals(droppedThing, thingWhereItWasDropped)
    ' Don't drop it
Else
    ' Drop it
End If

I couldn't find a good answer for this, although it seems like it must be a commonly encountered problem. So I used gbianchi's answer in the following way:

public bool DraggingFromFileLinkDGV { get; set; }
void grdFiles_MouseDown(object sender, MouseEventArgs e)
{
    this.DraggingFromFileLinkDGV = true;
}
void grdFiles_MouseLeave(object sender, EventArgs e)
{
    this.DraggingFromFileLinkDGV = false;
}

void grdFiles_DragDrop(object sender, DragEventArgs e)
{
    // Avoid DragDrop's on jittery DoubleClicks
    if (this.DraggingFromFileLinkDGV) return;

    // Your DragDrop code here ...
}

Now, I actually did this specifically to prevent "wandering" double clicks where the mouse moves a bit between a double click. This prevents double clicks registering as drag drops as well as answering the OPs question.

Mind you, it doesn't appear to work 100% of the time. Apparently some events are "lost" in like 1 out 20 cases. I haven't identified exactly what varies in those situations where it registers a drop onto itself. In the case of preventing double clicks registering as drag drops, 95% is good enough because it was just being put in place to avoid the annoyance. If you need something that is 100% effective, you may have to try something else or figure out why it doesn't work in those few cases.

One way is to store a string description of what you are dragging in the DataObject when you start dragging, ie:

Dim dataObj As New DataObject
...
dataObj.SetText(G_SELF_DRAG_DROP_FLAG)

Then on DragEnter check to see if the flag is there:

Public Sub ProcessAttachment_DragEnter(ByRef e As System.Windows.Forms.DragEventArgs)

    ' prevent dragging onto self
    Dim s = e.Data.GetData(DataFormats.Text)
    If s IsNot Nothing Then
        If s.contains(G_SELF_DRAG_DROP_FLAG) Then
            e.Effect = DragDropEffects.None
            Exit Sub
        End If
    End If

    ...

End Sub

Setting the flag to false in the MouseLeave event did not work correctly for me. MouseLeave kept being called as soon as I called DoDragDrop.

I finally got it to work right as follows:

A) I create a private bool DraggingFromHere flag
B) Right before calling DoDragDrop, I set this.DraggingFromHere = true
C) In the MouseUp event, I set this.DraggingFromHere = false
D) In the DragDro event, I simply to this:
    if(this.DraggingFromHere) return;

Carlos A Merighe

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top