Drag and Drop Rows of Datagrid View Winform C#
c#, datagridview
Solution
I much prefer using mouse events over actual drag&drop events for this when doing d&d within an application.
1 - Unbound example
Here is a simple example that uses the mouse events to drag rows around while diplaying one `Cell` value in a `Label`.
It inserts the row after the one you drop it on.
The `dragLabel` part is optional..
First we declare two helper variables at class level:
int dragRow = -1;
Label dragLabel = null;
Then we code the `CellMouseDown` to prepare the `Label`..:
private void dataGridView1_CellMouseDown(object sender,DataGridViewCellMouseEventArgs e)
{
if (e.ColumnIndex<0 || e.RowIndex < 0) return;
dragRow = e.RowIndex;
if (dragLabel == null) dragLabel = new Label();
dragLabel.Text = dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString();
dragLabel.Parent = dataGridView1;
dragLabel.Location = e.Location;
}
In the `MouseMove` we just move the Label. But as the `MouseDown` usually starts a cell selection we clear the selection..
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && dragLabel != null)
{
dragLabel.Location = e.Location;
dataGridView1.ClearSelection();
}
}
The real work is in the `MouseUp`. We need a `HitTest` to find out which, if any, row we are on. We also need to calculate the target row depending on the direction of the drag.
Finally we clean up the `Label`..
private void dataGridView1_MouseUp(object sender, MouseEventArgs e)
{
var hit = dataGridView1.HitTest(e.X,e.Y);
int dropRow = -1;
if (hit.Type != DataGridViewHitTestType.None)
{
dropRow = hit.RowIndex;
if (dragRow >= 0 )
{
int tgtRow = dropRow + (dragRow > dropRow ? 1 : 0);
if (tgtRow != dragRow)
{
DataGridViewRow row = dataGridView1.Rows[dragRow];
dataGridView1.Rows.Remove(row);
dataGridView1.Rows.Insert(tgtRow, row);
dataGridView1.ClearSelection();
row.Selected = true;
}
}
}
else { dataGridView1.Rows[dragRow].Selected = true;}
if (dragLabel != null)
{
dragLabel.Dispose();
dragLabel = null;
}
}
A few notes:
Make sure no row is new or modified or you can't move it. It took me awhile to realize that I had to switch off `AllowUserToAddRows` before adding the rows initially..
The treatment of selections is up to you. I chose to select the dragged row if the drop fails. And I chose to let it fail when dragging into the empty space.
Update:
2 - DataBound example
If the DGV is data-bound you can't move the rows directly. Instead you need to move the rows in the `DataSource`.
Let's assume you have a `DataTable DT`. Then you can remove rows from it and insert rows at any position. (Quite different from SQL DBMS tables!)
Note that a `DataRow` loses its values once removed from the `DataTable`. Therefore we need to clone the values before we remove the row. Other than that the code is pretty much the same. Simply replace the innermost condition with this:
if (tgtRow != dragRow)
{
DataRow dtRow = DT.Rows[dragRow];
DataRow newRow = DT.NewRow();
newRow.ItemArray = DT.Rows[dragRow].ItemArray; // we need to clone the values
DT.Rows.Remove(dtRow);
DT.Rows.InsertAt(newRow, tgtRow);
dataGridView1.Refresh();
dataGridView1.Rows[tgtRow].Selected = true;
}
Problem
I want to Drag Rows from certain position to another position in same grid view. The Other rows should automatically adjust according to the Drag and Drop. Thank You