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