DGVs: Dragdrop copy + reorder with givefeedback

Ultrawhack

Well-known member
Joined
Jul 5, 2006
Messages
164
Location
Canada
Programming Experience
3-5
  • DGV1 is a databound DGV and DGV2 is unbound.
  • Both are Selectionmode=Fullrowselect, multiselect=false, AllowUserToAddRows=false
  • DGV1 rowselected can be dragdropped and copied to DGV2.
  • DGV2 rowselected should be reorderable within DGV2.
  • Both DGVs Givefeedback should use rowselected, column 1 as cursor.
1. With reference to JohnH's solution to dragdropping and copying items from databound DGV to unbound DGV2 in this thread

I am trying to take this a step further.

2. GiveFeedback on Dragdrop
I need to DGV1’s rowselected to givefeedback as items are being copied as per this thread. It seems logical that rowselected, column1 should be used as the cursor.

3. Reorder Rows on DGV2 with GiveFeedback
DGV2’s rows should be reorderable as per DGV FAQs. Also DGV2 should givefeedback on dragdrop reorder.

I am having real problems with getting all 3 modules to work together and I request help from the experts on this forum.

Thanks in advance.
 
Last edited:
You can use the same method for drawing the image as the other example, the text you ask should be found in the first item in ItemArray of the DataRowView.Row (this also handles reorder columns as you asked before).

For both DGVs GiveFeedback you set the current cursor to the current text cursor, same as the listbox example linked.

Dragging from DGV1 to DGV2 you got solved in the other thread.

Reorder rows is the same as setting up drag&drop within a single DGV, since you are not confortable with how this is done you try to code this as a single task first, not mix everything you want to do into one big problem, create a new project with only a single DGV and add a column and some items (unbound). Try to make reorder happen with this first so you understand what it takes. I think I have explained this to you before, if not the basic principle is as always for drag&drop move operation, you decide some data to send and on drop remove from the source and add to the target. Here source and target is the same control/collection so there is just this little logical puzzle to solve about what index to insert item after it was removed from it's previous index. Try it out and you will see by moving an item before or after it previous index. Reply with code if this is something you specifically can't work out.

When you have a clean understanding of how to solve each single problem it will be a piece of cake putting them together to the final solution. What you have to think about specifically here is that DGV2 will accept two different drops in the same event handler method, one copy-drop from DGV1 and one move-drop from itself, these two drops are very easy to distinguish between since they are different dragdrop-types (copy/move).
 
Thanks for the pointers. I have been able to implement 1 & 2 but have not been able to correctly trigger reorder on DGV2's dragdrop. Cannot figure the code to distinguish between IF it is a COPY from DGV1 or MOVE within DGV2
 
Last edited:
The DragDrop event handler give you this information in e.Effect:
VB.NET:
If e.Effect = DragDropEffects.Copy Then
'...
ElseIf e.Effect = DragDropEffects.Move Then
'...
End If
 
Here's my DGV2 dragdrop code (in the sample). I'm missing something somewhere...

VB.NET:
[SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] DataGridView2_DragDrop([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Windows.Forms.DragEventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] DataGridView2.DragDrop
[/SIZE][SIZE=2][COLOR=#008000]'If items being copied from DGV1 then Copy
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] e.Effect = DragDropEffects.Copy [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] e.Data.GetDataPresent([/SIZE][SIZE=2][COLOR=#0000ff]GetType[/COLOR][/SIZE][SIZE=2](DataRowView)) = [/SIZE][SIZE=2][COLOR=#0000ff]True[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] DataGridView2.Columns.Count = 0 [/SIZE][SIZE=2][COLOR=#0000ff]Then[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#008000]'add columns
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]For[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Each[/COLOR][/SIZE][SIZE=2] col [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] DataGridViewColumn [/SIZE][SIZE=2][COLOR=#0000ff]In[/COLOR][/SIZE][SIZE=2] DataGridView1.Columns
DataGridView2.Columns.Add(col.Clone)
[/SIZE][SIZE=2][COLOR=#0000ff]Next
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#008000]'get data
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] drow [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] DataRowView = e.Data.GetData([/SIZE][SIZE=2][COLOR=#0000ff]GetType[/COLOR][/SIZE][SIZE=2](DataRowView))
[/SIZE][SIZE=2][COLOR=#008000]'add row
[/COLOR][/SIZE][SIZE=2]DataGridView2.Rows.Add(drow.Row.ItemArray)
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Else
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#008000]'If dragdrop within DGV2 then move items
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] e.Effect = DragDropEffects.Move [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#008000]' The mouse locations are relative to the screen, so they must be 
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#008000]' converted to client coordinates.
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] clientPoint [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Point = DataGridView2.PointToClient([/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Point(e.X, e.Y))
[/SIZE][SIZE=2][COLOR=#008000]' Get the row index of the item the mouse is below. 
[/COLOR][/SIZE][SIZE=2]rowIndexOfItemUnderMouseToDrop = DataGridView2.HitTest(clientPoint.X, clientPoint.Y).RowIndex
[/SIZE][SIZE=2][COLOR=#008000]' If the drag operation was a move then remove and insert the row.
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] (e.Effect = DragDropEffects.Move) [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] rowToMove [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] DataGridViewRow = [/SIZE][SIZE=2][COLOR=#0000ff]CType[/COLOR][/SIZE][SIZE=2](e.Data.GetData([/SIZE][SIZE=2][COLOR=#0000ff]GetType[/COLOR][/SIZE][SIZE=2](DataGridViewRow)), DataGridViewRow)
DataGridView2.Rows.RemoveAt(rowIndexFromMouseDown)
DataGridView2.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove)
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2] [/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE]
 
I had a look at your project. You don't need to do anything in mousemove event, and you should absolutely not draw the image in this event. You know all you need to know in the mousedown event for dragdrop operation to start and image to be drawn.

In DragOver you misses something because you set here effect to be copy only, this in cancels the move operation you started, you could check type of data since you send different data (DataGridViewRow or DataRowView).

You really should do row reorder with dragdrop as a separate project to get this working and out of all other possible problems. Two little tips for drop, first: you don't need the index from mousedown because the row dropped can be removed with the Remove method, second: remove the row then do the hittest to find index to drop then insert row. This saves you the trouble of taking into account if removed row is before drop index thus will reindex all items after this index when removed, so you'll miss insert by one. By all means try out both methods, but there is a simple logic to it, and you have to accommodate either way.

Nice catch getting the dragdrop mouse point to client point! ;) Also remember to catch this index -1 and provide a default drop index if so, make it first or last item or don't reorder at all when this happens.
 
OK, I corrected DGV2's dragover code..
VB.NET:
[COLOR=blue]Private[/COLOR][COLOR=blue]Sub[/COLOR][COLOR=black] DataGridView2_DragOver([/COLOR][COLOR=blue]ByVal[/COLOR][COLOR=black] sender [/COLOR][COLOR=blue]As[/COLOR][COLOR=black] System.Object, [/COLOR][COLOR=blue]ByVal[/COLOR][COLOR=black] e [/COLOR][COLOR=blue]As[/COLOR][COLOR=black] System.Windows.Forms.DragEventArgs) [/COLOR][COLOR=blue]Handles[/COLOR][COLOR=black] DataGridView2.DragOver[/COLOR]
[COLOR=blue]If[/COLOR][COLOR=black] (e.Data.GetDataPresent([/COLOR][COLOR=blue]GetType[/COLOR][COLOR=black](DataRowView)) = [/COLOR][COLOR=blue]True[/COLOR][COLOR=black]) [/COLOR][COLOR=blue]Then[/COLOR][COLOR=black] _[/COLOR]
[COLOR=black]e.Effect = DragDropEffects.Copy[/COLOR]
 
[COLOR=blue]If[/COLOR][COLOR=black] (e.Data.GetDataPresent([/COLOR][COLOR=blue]GetType[/COLOR][COLOR=black](DataGridViewRow)) = [/COLOR][COLOR=blue]True[/COLOR][COLOR=black]) [/COLOR][COLOR=blue]Then[/COLOR][COLOR=black] _[/COLOR]
[COLOR=black]e.Effect = DragDropEffects.Move[/COLOR]
[COLOR=blue]End[/COLOR][COLOR=blue]Sub[/COLOR]

and I seem to have got it working. Thank you for your help. I will keep testing & post back in case of errors.
 
Last edited:
Ever heard about "Else" and "ElseIf"? lol.
Now you've lost me ! Need help with DGV2 dragover and dragdrop pls.
Excuse me? You just did DragOver.

What is the problem about DragDrop event handler?

You can look up any dragdrop reorder example they are all the same, as all dragdrop examples are the same. If you know one you know them all. There is no point for me to spoonfeed you with every little detail or just write the code for you, you'll learn nothing from that.
 
Yes, thanks. For someone who's new to VB.Net, I think I'm doing quite well. Unfortunately there is a complete absence of documentation for this kind of application I have suggested. So we have to glean off forums like these. And for that I am grateful. Spoonfeed?? lol
 
Good you're getting progress, but i don't agree there is little documentation. Drag&drop is well documented for every event, also with walkthrough, and the basic principle of the series of events is the same for ALL drag&drop operations, there exist no exception whatsoever. Drawing text to graphics is documented. Getting a row from DGV is documented. Every little programming step you have to do is well documented, all namespaces, all classes, all methods, all properties, all events, and just about every interaction between these, the framework class library and MSDN got it all, but I agree it takes some time reading much of this. A programmers job is to first break the main objective into all these smaller tasks, then making them work together. If you have the knowledge about the smaller tasks you can solve every little problem, then it is also easy to separate the problems when getting the pieces to interact. That's the reason it is adviceable for the novist programmer to make smaller projects solving the basic operation first. If you can make one project drag&drop from one control to another, and one project drag&drop within same control, there isn't much to it making a project that incorporates both these operations. There is nothing complicated with what you are doing here, just two very basic drag&drop operations including the easiest possible graphics work to draw a image used as cursor.

Spoonfeed yes? You're asking the same questions over again. How can drag from listbox to listbox? How can I drag from Datagridview to Datagridview. How can I drag reorder listbox? How can I drag reorder Datagridview? How to make drag cursor for listbox? How to make drag cursor for Datagridview?

If I took a few minutes writing the code would you ask the same question again? oh yes, you would be back next week asking how to drag from listview to listview. from listbox to datagridview. from textbox to combobox. etc. Sorry if you misunderstand this, but I'm trying to emit some basic knowledge about drag&drop operations here.
 
And now that yelling is done and my points explicitly made and you probably finished or discarded the whole thing out of frustrations.. hahah :) here is the project fixed and cleaned from what you posted, hope the advice and this code sample makes the drag&drop operation clear. I also included the three code lines about column reorder automation we talked about.
 

Attachments

  • vbnet20-Sample_dgv_2_dgv_row_dragdrop.zip
    112.8 KB · Views: 72
I'm going to respond to this flaming very positively and say, dear moderator - what are these forums here for ? To ask questions and share knowledge.

Now I have been polite and said my please and thank yous.

If you can show me one complete code sample out there where this DGV2DGVCopyReorder or Listbox2ListboxCopyReorder is available for us learners to study, I'll be surprised.

Because I have done the googling and it did not exist. But it is available now, thanks to these forums. You know why ? BECAUSE I ASKED...

(and was willing to take the long lecture).... my goodness, how long did it take you to type in that long venting ?
Thanks for the sample, buddy.
 
"Walkthrough: Performing a Drag-and-Drop Operation in Windows Forms" - this is just about all you need to learn and do drag&drop. Everything else is just minor variants, little tweaks to get you head around. For instance how to get a row from DataGridView or a value from this row has nothing to do with drag and drop operation itself. It's really that simple.
 
In your code sample after the DGV1 to DGV2 dragdrop and DGV2 reorder, the DGV2 selectedrow appears incorrectly. I know that I can set focus by setting the CurrentCell property. But Row selection is independent from focus.

How can I ensure that the selectedrow and pointer remain on the DGV2 row that was just processed ? If I copied apples row or reordered apples row, then apples row should remain selected.
 
Back
Top