Question Drag & Drop Between 2 Datagrids Between 2 MDI Child Forms

pidyok

Member
Joined
Feb 10, 2009
Messages
19
Programming Experience
Beginner
Ive been working on this project of mine for some time now... though im not involved in IT in my current company, im just trying to help to at least have their system computerized (they are still doing it manually by paper & calculator)... I have one problem though which made me stick for 2 days (and still counting) without progress... How To Drag & Drop Between 2 Datagrids Between 2 similar MDI Child Forms >>> anybody can help me with the above topic??? my apologies, im not that adept in VB.net programming... thank you very much... :(:(:(
 

Attachments

  • Manifest.jpg
    Manifest.jpg
    52.5 KB · Views: 79
What would you want to dragndrop? A row, a cell, a cells value?
I tried dragndropping between 2 MDI children and it doesn't seem to work.
I suggest maybe you try creating a global variable of the type you want
to copy (move) and create it when the drag starts. Then pick it up on the other form when the drag ends. I hope somebody with more experience
can help you!

This is what I tried but it always gives me the denied mouse cursor:

VB.NET:
Private Sub DataGridView1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragDrop
        Dim dgvc As DataGridViewCell = DirectCast(e.Data.GetData(GetType(DataGridViewCell)), DataGridViewCell)
        MsgBox(dgvc.Value)
    End Sub

    Private Sub Form3_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Me.MdiParent = Form1
        DataGridView1.Rows.Add("test from form3")
    End Sub

    Private Sub DataGridView1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragEnter
        If e.Data.GetDataPresent(GetType(DataGridViewCell)) Then
            e.Effect = DragDropEffects.Copy
        Else
            e.Effect = DragDropEffects.None
        End If
    End Sub
    Private Sub DataGridView1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGridView1.MouseDown
        DataGridView1.DoDragDrop(DataGridView1.CurrentCell, DragDropEffects.Copy)
    End Sub

info about dragndrop: http://msdn.microsoft.com/en-us/library/aa289508(VS.71).aspx

grtz
 
thanks ill try that one out when i come home... thanks again... btw, im trying to drag a row from one datagrid in a child form to another... and the dataset was filled from a query...
 
This is what I found (it's not mine) and thought useful for you: (search took me long enough ;))
It basically does what I said you should do.
Create 2 datatables with your data from both grids, pass index when
dragndropping. I haven't tried this code but I think it will help you on your
way!
I tried passing the rows themself but can't seem to find how to determine
type when dropped on the other form....... :(
Now this is only a graphical representation of the data. Your data won't be
affected by this. Just so you know.

VB.NET:
Imports System.Drawing  '<Added>
Public Class FrmDragGrid
    ' Some Properties that I have set for the Grid
    ' SelectionMode = FullRowSelect [For both the Grids]
    ' AllowDrop = True [For Grid DGV2]
    '
    '
    Dim DT1 As DataTable
    Dim DT2 As DataTable

    Private Sub FrmDragGrid_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        FillDataInGrids()
    End Sub

    Private Sub FillDataInGrids()
        DT1 = New DataTable
        DT2 = New DataTable

        'The First Table has four columns
        DT1.Columns.Add("Name", Type.GetType("System.String"))
        DT1.Columns.Add("Designation", Type.GetType("System.String"))
        DT1.Columns.Add("Department", Type.GetType("System.String"))
        DT1.Columns.Add("Salary", Type.GetType("System.String"))

        'Second has only two
        DT2.Columns.Add("RowNumber", Type.GetType("System.Int32")) '<Added>
        DT2.Columns.Add("Name", Type.GetType("System.String"))
        DT2.Columns.Add("Designation", Type.GetType("System.String"))

        'Now Add some Rows in the first DataTable
        Dim Dr As DataRow

        Dr = DT1.NewRow
        Dr("Name") = "Tom"
        Dr("Designation") = "Developer"
        Dr("Department") = "Engg"
        Dr("Salary") = "1000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Jerry"
        Dr("Designation") = "Developer"
        Dr("Department") = "Engg"
        Dr("Salary") = "1000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Micky"
        Dr("Designation") = "Analyst"
        Dr("Department") = "Engg"
        Dr("Salary") = "2000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Mini"
        Dr("Designation") = "Analyst"
        Dr("Department") = "Engg"
        Dr("Salary") = "2000"
        DT1.Rows.Add(Dr)

        Dr = DT1.NewRow
        Dr("Name") = "Donald"
        Dr("Designation") = "Manager"
        Dr("Department") = "Engg"
        Dr("Salary") = "3000"
        DT1.Rows.Add(Dr)

        'Now Bind the DataGrids to these table
        DGV1.DataSource = DT1
        DGV2.DataSource = DT2

    End Sub

    Private Sub DGV1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DGV1.MouseDown
        'Get the Index of Row which is being Dragged
        'We would use this Index on Drop to identify which Row was dragged and get the values from that row
        Dim Index As Integer
        Index = DGV1.HitTest(e.X, e.Y).RowIndex
        If Index > -1 Then
            'Pass the Index as "Data" argument of the DoDragDrop Function
            IsReOrder = False
            DGV1.DoDragDrop(Index, DragDropEffects.Move)
        End If
        'NOTE: A better approach would be to Get the Primary Key value of the Row and instead of Index
        'Set this Primary Key value in the Data argument of the DoDragDrop, and in DragDrop event get the Primary Key 
        'From the argument and based on the Primary Key get the values from the DataTable
    End Sub

    Private Sub DGV2_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DGV2.DragOver
        'Just to Show a mouse icon to denote drop is allowed here
        e.Effect = DragDropEffects.Move
    End Sub

    Private Sub DGV2_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DGV2.DragDrop
        '<Function has changed>
        Try
            'Get the Index value that we stored in the Data in the MouseDown event
            'In case we stored a PrimaryKey value here in place of Index, we would get that by Type casting it to its type
            If IsReOrder Then
                Dim SrcIndex As Integer = Convert.ToInt32(e.Data.GetData(Type.GetType("System.Int32")))
                Dim clientPoint As Point = DGV2.PointToClient(New Point(e.X, e.Y))
                Dim DestIndex As Integer = DGV2.HitTest(clientPoint.X, clientPoint.Y).RowIndex
                'Now based on the Index get the data in the Cells
                'Again if we had Primary Key value here we would have used the underlying DataTable DT1 to get the data for that key
                ReOrderGridRows(SrcIndex, DestIndex)
            Else
                Dim Name As String
                Dim Desig As String
                
                For Each DGR As DataGridViewRow In DGV1.SelectedRows
                    Name = DGR.Cells("Name").Value.ToString
                    Desig = DGR.Cells("Designation").Value.ToString
                    Dim Dr As DataRow
                    Dr = DT2.NewRow
                    Dr("RowNumber") = DT2.Rows.Count + 1
                    Dr("Name") = Name
                    Dr("Designation") = Desig
                    DT2.Rows.Add(Dr)
                Next
            End If

        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            IsReOrder = False
        End Try

    End Sub

    Private Sub FrmDragGrid_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
        If e.KeyChar = Convert.ToChar(Keys.Escape) Then
            Close()
        End If
    End Sub

    Dim RowIndexofDraggedRow As Integer
    Dim IsReOrder As Boolean

    Private Sub DGV2_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DGV2.MouseDown
        RowIndexofDraggedRow = DGV2.HitTest(e.X, e.Y).RowIndex
        If RowIndexofDraggedRow > -1 Then
            IsReOrder = True
            DGV2.DoDragDrop(RowIndexofDraggedRow, DragDropEffects.Move)
        End If
    End Sub

    Private Sub ReOrderGridRows(ByVal SourceIndex As Integer, ByVal DestinationIndex As Integer)
        If SourceIndex < 0 OrElse SourceIndex > DGV2.Rows.Count Then Return
        If DestinationIndex < 0 OrElse DestinationIndex > DGV2.Rows.Count Then Return

        Dim SrcRow As DataRow
        SrcRow = DT2.NewRow
        SrcRow("RowNumber") = DestinationIndex
        SrcRow("Name") = DT2.Rows(SourceIndex)("Name")
        SrcRow("Designation") = DT2.Rows(SourceIndex)("Designation")

        DT2.Rows.RemoveAt(SourceIndex)
        DT2.Rows.InsertAt(SrcRow, DestinationIndex)

        For i As Integer = 0 To DT2.Rows.Count - 1
            DT2.Rows(i)("RowNumber") = i + 1
        Next
    End Sub
End Class

------------------
I tried to Remove the Looping in the ReOrder function, but could'nt think of a better way. 
Also there are a few points to remember here....
#1. While dragging Rows from One Grid to another it copies all the SELECTED Rows, this is in order to implement multiple row drops. Try this in the form, Select say row 2 in the first grid,  Now drag row 3 without selecting it. Row 2 would be moved to the other Grid not Row 3, this might confuse Users but you can educate them that they need to first click on the 3rd row and select it then drag it.

#2. Suppose the height of the second grid is so much that only 10 rows are visible, Add 50 Rows to the grid so that you have a scrollbar. Now move the scrollbar to the top so that the first row is visible. Try moving the First row to the 50th position.....You can't.......The scrollbars would not move while you are dragging a row. The way out.....Drop the First row at the last visible row position, then scroll down again start dragging that row so in a few drag-drops you would reach the bottom......
Not very elegant? provide an alternat way for the users to Re-Order the rows, say you can have a right click menu which says "Move to x Position" or some other way.....
 
Last edited:
grmbl, i tried but somehow, it doesnt drop the data unto the datagrid of the other form... i want to drag a row completely by the way... i reached a point where i used textboxes to replace the datagrid for the drag drop functionality where i was able to do so... but somehow having all textboxes to act as cells (textboxes arranged such that it looked like a datagrid) slowed my application too much everytimei create or open a new child form... not only that, auto sorting or sorting the data was a forseeable mess... until now, im still waiting for somebody to help me further on this... hopefully hardcore gurus in vb.net could help me... =) cheers
 
Would it be a possibilty to make class that inherits dataobject then define the object as a datarow? I have done this with buttons and labels for dragdrop operations b/t diff controls. Just an idea. I can post the class structure tomorrow.
 
I haven't the time to check to see if this works b/t MDI forms - and I don't use these.
VB.NET:
Public Class DRGR
  Inherits DataObject
  Public Sub New()
  End Sub
  Public Sub New(ByVal dgvr As DataGridViewRow)
     Me.SetData("DGVR", False, DataGridViewRow)
  End Sub
End Class
Usage in the GDV's drag events
VB.NET:
If e.Data.GetDataPresent("DGVR") Then 
Dim dgv As DataGridView = CType(sender, DataGridView)(
Then the logic to add this to the DGV in the DragDrop event.
Hopefully someone smarter than myself will chime in if this not the right approach.
 
Try this format:
VB.NET:
 Private Sub dgv_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
                    Handles dgvA.MouseDown, dgvB.MouseDown
        Dim thisDgv As DataGridView = CType(sender, DataGridView)
        If e.Button = Windows.Forms.MouseButtons.Right Then
            thisDgv.DoDragDrop(thisDgv, DragDropEffects.Move)
        End If
    End Sub
 
    Private Sub dgv_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) _
                     Handles dgvA.DragDrop, dgvB.DragDrop
        Dim thisDGV As DataGridView = CType(sender, DataGridView)
        Dim Source As DataGridView = e.Data.GetData("System.Windows.Forms.DataGridView", True)
        If Source Is thisDGV Then Exit Sub
 
        Dim sourceTable As DataTable = CType(Source.DataSource, DataTable)
        Dim targetTable As DataTable = CType(thisDGV.DataSource, DataTable)
 
        Dim RowsToMove As New List(Of DataRow)
        For Each dvgr As DataGridViewRow In Source.SelectedRows
            RowsToMove.Add(CType(dvgr.DataBoundItem, DataRowView).Row)
        Next
        For Each dr As DataRow In RowsToMove
            Dim targetRow As DataRow = targetTable.NewRow
            targetRow(0) = dr(0)
            targetRow(1) = dr(1)
            targetTable.Rows.InsertAt(targetRow, 0)
            sourceTable.Rows.Remove(dr)
        Next
 
    End Sub
 
    Private Sub dgv_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) _
                   Handles dgvA.DragEnter, dgvB.DragEnter
        Dim thisDGV As DataGridView = CType(sender, DataGridView)
        Dim Source As DataGridView = e.Data.GetData("System.Windows.Forms.DataGridView", True)
        If Source Is thisDGV Then
            e.Effect = DragDropEffects.None
        Else
            e.Effect = DragDropEffects.Move
        End If
    End Sub
 
newguy, thanks... but i tried this already... but the problem is, i have a single form with a datagrid (let's call it DGV1)... and the same form is being relaunched everytime i create a new child... as with this code...

Private Sub ShowNewForm(ByVal sender As Object, ByVal e As EventArgs) Handles NewToolStripMenuItem.Click, NewToolStripButton.Click, NewWindowToolStripMenuItem.Click
m_ChildFormNumber += 1
Dim ChildForm As New frmManifest 'System.Windows.Forms.Form

ChildForm.MdiParent = Me

ChildForm.Text = "Manifest " & m_ChildFormNumber
ChildForm.Name = "frmManifest" & m_ChildFormNumber
ChildForm.Show()

If m_ChildFormNumber > 1 Then Me.LayoutMdi(MdiLayout.TileVertical)

End Sub


with such code, the child forms are createdwith the same datagrid "DGV1" as shown above... based on the code you have given, for which i've tried as well before, i cannot have dgvA & dgvB... cos at times, i'll have close to 6 manifest list which is placed on similar childs coming from a single base form with dgv1... therefore, if i name dgvA & dgvB as dgv1 only would fire drag event even on a click of a mouse...

anyway, i thank you for your continued help...

cheers!!!
 
You can handle the appropriate events for your controls regardless of their names and placement.
 
...

im trying to handle the events by determining the child form's name and working on such, apparently, im ending up getting the same datagrid source for "source and destination"... hopefully, someone could point me to the right direction....

Private Sub frmManifest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
dtDate.CustomFormat = "dd MMM yy"
dtDate.Value = Now
End Sub

Private Sub dgvOriginating_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles dgv1.MouseDown

dgv1.DoDragDrop(dgv1.SelectedRows, DragDropEffects.Copy)

End Sub


Private Sub dgvDropping_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles dgv1.DragEnter

Dim i As Integer
For i = 0 To e.Data.GetFormats().Length - 1
If e.Data.GetFormats()(i).Equals _
("System.Windows.Forms.DataGridViewSelectedRowCollection") Then

e.Effect = DragDropEffects.Copy
End If
Next
End Sub

Private Sub dgvDropping_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles dgv1.DragDrop
Dim row, lclrow As DataGridViewRow
Dim ii As Integer


If e.Effect = DragDropEffects.Copy Then
For ii = 0 To e.Data.GetFormats().Length - 1
Console.WriteLine(e.Data.GetFormats()(ii).ToString)
Next
Dim rc As DataGridViewSelectedRowCollection = e.Data.GetData("System.Windows.Forms.DataGridViewSelectedRowCollection")



For Each row In rc
lclrow = New DataGridViewRow
lclrow.CreateCells(dgv1)
For ii = 0 To lclrow.Cells.Count - 1
lclrow.Cells(ii).Value = row.Cells(ii).Value
Next
dgv1.Rows.Add(lclrow)
Next

End If



now im trying with Listview instead since the code below gives me a bit of hope... slightly off topic now but still working on copying the entire row or including listviewitems (viewtype: list)... as the code below allows me to drag the main item onLY but doesnt include the subitems in the row...

The listview code i have:

Private Sub ListView_ItemDrag(ByVal sender As Object, ByVal e As _
System.Windows.Forms.ItemDragEventArgs) Handles lsvManifest.ItemDrag
Dim myItem As ListViewItem
Dim myItems(sender.SelectedItems.Count - 1) As ListViewItem
Dim i As Integer = 0

For Each myItem In sender.SelectedItems
myItems(i) = myItem
i = i + 1
Next

sender.DoDragDrop(New DataObject("System.Windows.Forms.ListViewItem()", myItems), DragDropEffects.Move)
End Sub

Private Sub ListView_DragEnter(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles lsvManifest.DragEnter

If e.Data.GetDataPresent("System.Windows.Forms.ListViewItem()") Then
e.Effect = DragDropEffects.Move
Else
e.Effect = DragDropEffects.None
End If
End Sub

Private Sub ListView_DragDrop(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles lsvManifest.DragDrop
Dim myItem As ListViewItem
Dim myItems() As ListViewItem = e.Data.GetData("System.Windows.Forms.ListViewItem()")
Dim i As Integer = 0

For Each myItem In myItems

sender.Items.Add(myItems(i).Text)
If sender Is lsvManifest Then
lsvManifest.Items.Remove(lsvManifest.SelectedItems.Item(0))
Else
lsvManifest.Items.Remove(lsvManifest.SelectedItems.Item(0))
End If
i = i + 1
Next
End Sub



either listview or datagrid view will work for me so im trying to work on either of the approach... thanks!
 
Last edited:
Back
Top