I have copied some code and modified it to suit my application. And I will continue to tweak and clean up the code until I am statisfied with it. But I have encountered a little error. I have two datagridviews and wish to move datagridrows from one to another. However, while the drag&drop events all fire, the dataGridView_Routes_DragDrop() will execute the log command because there is no data in e.Data.GetData. What have I done wrong? Am I missing something? I've tried to look through several guides but nothing specifically covers this issue.
How can I get the datagrid pass the dragged datagridrow over to the other datagrid?
/* Drag & Drop */
private Rectangle dragBoxFromMouseDown;
private int rowIndexFromMouseDown;
private void dataGridView_Trips_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
// If the mouse moves outside the rectangle, start the drag.
if (dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(e.X, e.Y))
{
// Proceed with the drag and drop, passing in the list item.
DragDropEffects dropEffect = dataGridView_Trips.DoDragDrop(dataGridView_Trips.Rows[rowIndexFromMouseDown], DragDropEffects.Copy);
}
}
}
private void dataGridView_Trips_MouseDown(object sender, MouseEventArgs e)
{
// Get the index of the item the mouse is below.
rowIndexFromMouseDown = dataGridView_Trips.HitTest(e.X, e.Y).RowIndex;
if (rowIndexFromMouseDown != -1)
{
// Remember the point where the mouse down occurred.
// The DragSize indicates the size that the mouse can move
// before a drag event should be started.
Size dragSize = SystemInformation.DragSize;
// Create a rectangle using the DragSize, with the mouse position being
// at the center of the rectangle.
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
}
else
// Reset the rectangle if the mouse is not over an item in the ListBox.
dragBoxFromMouseDown = Rectangle.Empty;
}
private void dataGridView_Routes_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void dataGridView_Routes_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(DataRowView)))
{
// The mouse locations are relative to the screen, so they must be
// converted to client coordinates.
Point clientPoint = dataGridView_Routes.PointToClient(new Point(e.X, e.Y));
// If the drag operation was a copy then add the row to the other control.
if (e.Effect == DragDropEffects.Copy)
{
DataGridViewRow rowToMove = e.Data(typeof(DataGridViewRow)) as DataGridViewRow;
dataGridView_Routes.Rows.Add(rowToMove);
}
}
else
{
log("Geen data! #01", "Fout");
}
}
/* End Drag & Drop */
I don't know. But the following function has been adjusted and it works as intended. Not quite sure how the previous code broke.
EDIT: The typeof was written with DataViewRow instead of DataGridViewRow. Fail.
private void dataGridView_Routes_DragDrop(object sender, DragEventArgs e)
{
try
{
if (e.Data.GetDataPresent(typeof(DataGridViewRow)))
{
// The mouse locations are relative to the screen, so they must be
// converted to client coordinates.
Point clientPoint = dataGridView_Routes.PointToClient(new Point(e.X, e.Y));
// If the drag operation was a copy then add the row to the other control.
if (e.Effect == DragDropEffects.Copy)
{
DataGridViewRow Row = (DataGridViewRow)e.Data.GetData(typeof(DataGridViewRow));
dataGridView_Routes.Rows.Add(Row.Cells[0].Value, Row.Cells[1].Value, Row.Cells[2].Value);
}
}
else
{
log("Geen data! #01", "Fout");
}
}
catch (Exception msg)
{
log(msg.Message,"Fout");
}
}
This solution is for the people who have the datagridViews bound to customObjects. It works like a charm with multiple selection. Suggestions are accepted.
Assuming you want to drag from datagridview1 to datagridview2
//datagridview1 is bound to this BindingList
BindingList<myObject> object_bound_list1;
//datagridview2 is bound to this BindingList
BindingList<myObject> object_bound_list2;
List<myObject> selected_Object_list = new List<myObject>();
List<int> selected_pos_list = new List<int>();
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
// Proceed with the drag and drop, passing in the list item.
DragDropEffects dropEffect = dataGridView1.DoDragDrop(
selected_Object_list,
DragDropEffects.Move);
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
// Get the index of the item the mouse is below.
int rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;
//if shift key is not pressed
if (Control.ModifierKeys != Keys.Shift && Control.ModifierKeys != Keys.Control)
{
//if row under the mouse is not selected
if (!selected_pos_list.Contains(rowIndexFromMouseDown) && rowIndexFromMouseDown > 0)
{
//if there only one row selected
if (dataGridView1.SelectedRows.Count == 1)
{
//select the row below the mouse
dataGridView.ClearSelection();
dataGridView1.Rows[rowIndexFromMouseDown].Selected = true;
}
}
}
//clear the selection lists
selected_Object_list.Clear();
selected_pos_list.Clear();
//add the selected objects
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
selected_Object_list.Add(object_bound_list1[row.Index]);
selected_pos_list.Add(row.Index);
}
}
private void dataGridView2_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void dataGridView2_DragDrop(object sender, DragEventArgs e)
{
if (e.Effect == DragDropEffects.Move)
{
foreach (var item in selected_Object_list)
{
object_bound_list2.Add(item);
}
}
}
Related
I got a Datagridview that is empty.
The user is able to drag and drop values from a list in to the Datagridview copying the text.. The user is also able to drag and drop values within the Datagrid view moving the text.
But what i also want is for the Rows to drag and drop able (changing the order they appear in).
I manged to do both individually by using the code provided from these 2 answers:
https://stackoverflow.com/a/21133200/10086705 (for cell to cell)
How could I Drag and Drop DataGridView Rows under each other? (For dragging rows).
The issue is they both use the same events, my current solution is using a check box to see which one to use. (Checked for row, unchecked for cells) Al tough this works i don't believe this is the most efficient/user friendly way.
This is the code for the dragging of the cells.
(Don't mind the try catches they are a temp solution.)
private Rectangle dragBoxFromMouseDown;
private object valueFromMouseDown;
private DataGridViewCell origin;
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
if (dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(e.X, e.Y))
{
try
{
DragDropEffects dropEffect = dataGridView1.DoDragDrop(valueFromMouseDown, DragDropEffects.Copy);
}
catch{}
}
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
origin = sender as DataGridViewCell;
var hittestInfo = dataGridView1.HitTest(e.X, e.Y);
if (hittestInfo.RowIndex != -1 && hittestInfo.ColumnIndex != -1)
{
valueFromMouseDown = dataGridView1.Rows[hittestInfo.RowIndex].Cells[hittestInfo.ColumnIndex].Value;
if (valueFromMouseDown != null)
{
origin = dataGridView1.Rows[hittestInfo.RowIndex].Cells[hittestInfo.ColumnIndex] as DataGridViewCell;
Size dragSize = SystemInformation.DragSize;
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
}
}
else
{
dragBoxFromMouseDown = Rectangle.Empty;
}
}
private void dataGridView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));
if (e.Effect == DragDropEffects.Copy)
{
string cellvalue = e.Data.GetData(typeof(string)) as string;
var hittest = dataGridView1.HitTest(clientPoint.X, clientPoint.Y);
if (hittest.ColumnIndex != -1 && hittest.RowIndex != -1)
{
try
{
if (dataGridView1[hittest.ColumnIndex, hittest.RowIndex].Value.ToString() != "")
{
DialogResult dialogResult = MessageBox.Show("Are you sure you want to replace this value?", "!", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
dataGridView1[hittest.ColumnIndex, hittest.RowIndex].Value = cellvalue;
try{origin.Value = "";}catch{}
}
else if (dialogResult == DialogResult.No){}
}
}
catch
{
dataGridView1[hittest.ColumnIndex, hittest.RowIndex].Value = cellvalue;
try{origin.Value = "";}catch{}
}
}
}
}
What i was hoping for is the possibility of an IF statement that checks if a row cell has been selected or if the RowHeader has been selected. In case of the cell it should only move the text from one cell to a other while if the RowHeader is selected it should move the row to a new location (without overwriting any existing row)
Have it solved, "if (dataGridView1.SelectedRows.Count == 1)" does the trick. If this is true it will move the row instead of the cell. Got it from the site below:
https://www.codeproject.com/Articles/811035/Drag-and-Move-rows-in-DataGridView-Control
In my project I have a ListView and I would like to open my ContextMenuStrip when I clicked right button in the large icon. I tried many things but I am unsuccessful. When I right click inside of ListView the ContextMenuStrip opens, but I want to see just when I right clicked the large icon.
Also I need to help about get the clicked icon's name (properties).
This is a quick and dirty solution; please do put more work into it than I did..
// a class level reference, prepare it where you want..
ContextMenuStrip ms = new ContextMenuStrip();
You should either code the MouseDown or the MouseUp event:
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
// disassociate from listview at first:
listView1.ContextMenuStrip = null;
// check for right button
if (e.Button != System.Windows.Forms.MouseButtons.Right) return;
// get item info:
ListViewHitTestInfo hi = listView1.HitTest(e.Location);
// no item hit:
if (hi.Item == null) return;
// calculate the image rectangle:
// this contains the unscrolled y coordinate:
Point iloc = listView1.GetItemRect(hi.Item.Index).Location;
// we combine it with the x-position:
Rectangle r = new Rectangle(new Point (hi.Item.Position.X, iloc.Y),
imageList1.ImageSize);
// no image hit:
if ( !r.Contains(e.Location) ) return;
// maybe prepare or change the menue now..
// here I display the image name from the keys array:
ms.Items[0].Text = imageList1.Images.Keys[hi.Item.ImageIndex];
ms.Location = e.Location;
// associate with listview and show
listView1.ContextMenuStrip = ms;
ms.Show();
}
Can you please try the following and let see wether it works or not...
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
if (listView1.FocusedItem.Bounds.Contains(e.Location) == true)
{
contextMenuStrip1.Show(Cursor.Position);
}
}
}
This should work
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
ListView listView = sender as ListView;
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
ListViewItem item = listView.GetItemAt(e.X, e.Y);
if (item != null)
{
item.Selected = true;
contextMenuStrip1.Show(listView , e.Location);
}
}
}
Search the listview item on mouse click location. If it is there, show the menu.........
I have a WinForm with DataGridView, my goal is to drag one column and drop it on other column index. I know column reordering is possible by using AllowUserToOrderColumns = true. But I have to perform other operations on DGV. That's why I need the target column index at a mouse-up event. To do that, I use HitTestInfo:
System.Windows.Forms.DataGrid.HitTestInfo myHitTest;
myHitTest = dataGrid1.HitTest(e.X, e.Y);
int p = myHitTest.ColumnIndex;
When I click on the first DGV column, this code runs and gives me the column's index (p). The problem is when I drop it on the other column of DGV, I'd like to know the target column's index, with the same code p = -1, I think because the HitTestInfo member returns a value on a MouseDown and not on a MouseUp. If anyone can tell me how to do it, it would be very great.
You can create two HitTestInfo objects, one in the MouseDown and one in the MouseUp.
IMO, you also should use the DataGridView.HitTestInfo class, not DataGrid.HitTestInfo and try to not call or name DataGridViews DataGrids, which is a similar but different Control from WPF!
DataGridView.HitTestInfo myHitTestDown, myHitTestUp;
int visibleColumnDown, visibleColumnUp;
private void dataGrid1_MouseUp(object sender, MouseEventArgs e)
{
myHitTestUp = dataGrid1.HitTest(e.X, e.Y);
visibleColumnUp = getVisibleColumn(dataGrid1, e.X);
}
private void dataGrid1_MouseDown(object sender, MouseEventArgs e)
{
myHitTestDown = dataGrid1.HitTest(e.X, e.Y);
visibleColumnDown = getVisibleColumn(dataGrid1, e.X);
}
Update: To find the visible index of a column after the columns have been reordered simply use:
dataGrid1.Columns[myHitTestUp.ColumnIndex].DisplayIndex;
Before I found that, I wrote this little helper function, which does the same:
int getVisibleColumn(DataGridView dgv, int x)
{
int cx = dgv.RowHeadersWidth;
int c = 0;
foreach (DataGridViewColumn col in dgv.Columns)
{
cx += col.Width; if ( cx >= x) return c; c++;
}
return -1;
}
To find out which Column was shuffled seems to be a bit harder. There is an event, which gets called for each column that was affected and it always gets called first for the one that was dragged along. Here is one way to do it:
Create to variables at class level:
List<DataGridViewColumn> shuffled = new List<DataGridViewColumn>();
DataGridViewColumn shuffledColumn = null;
Remember the first column:
private void dgvLoadTable_ColumnDisplayIndexChanged(
object sender, DataGridViewColumnEventArgs e)
{
if (shuffledColumn == null) shuffledColumn = e.Column;
}
Forget what happend before:
private void dgvLoadTable_MouseDown(object sender, MouseEventArgs e)
{
shuffledColumn = null;
}
Now you can use it. Selecting Columns is, however, not going well with shuffling them! If you do
shuffledColumn.Selected = true;
it will only be selected if the SelectionMode is either FullColumnSelector ColumnHeaderSelect- In either mode the shuffling will not work, I'm afraid..
You could use drag'n'drop for that.
Assume you have a Form with a DataGridView named dataGridView1.
Initially don't forget to allow drag'n'drop for DataGridView:
dataGridView1.AllowDrop = true;
The event handler which replaces the desired functionality of MouseUp would be the dataGridView1_DragDrop, and the target column's index is colIndexOfItemUnderMouseToDrop:
private Rectangle dragBoxFromMouseDown;
private int colIndexFromMouseDown;
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
// If the mouse moves outside the rectangle, start the drag.
if (dragBoxFromMouseDown != Rectangle.Empty &&
!dragBoxFromMouseDown.Contains(e.X, e.Y))
{
// Proceed with the drag and drop, passing in the list item.
dataGridView1.DoDragDrop(colIndexFromMouseDown, DragDropEffects.Move);
}
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
// Get the index of the item the mouse is below.
colIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).ColumnIndex;
if (colIndexFromMouseDown != -1)
{
// Remember the point where the mouse down occurred.
// The DragSize indicates the size that the mouse can move
// before a drag event should be started.
Size dragSize = SystemInformation.DragSize;
// Create a rectangle using the DragSize, with the mouse position being
// at the center of the rectangle.
dragBoxFromMouseDown = new Rectangle(
new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)),
dragSize);
}
else
// Reset the rectangle if the mouse is not over an item in the ListBox.
dragBoxFromMouseDown = Rectangle.Empty;
}
private void dataGridView1_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
// If the drag operation was a move then remove and insert the column.
if (e.Effect == DragDropEffects.Move)
{
// The mouse locations are relative to the screen, so they must be
// converted to client coordinates.
Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));
// Get the column index of the item the mouse is below.
int colIndexOfItemUnderMouseToDrop = dataGridView1.HitTest(clientPoint.X, clientPoint.Y).ColumnIndex;
if (colIndexOfItemUnderMouseToDrop == -1)
return;
colIndexOfItemUnderMouseToDrop = dataGridView1.Columns[colIndexOfItemUnderMouseToDrop].DisplayIndex;
// Now we have the column's display index.
if (e.Data.GetDataPresent(typeof(int)))
{
int colToMove = (int)e.Data.GetData(typeof(int));
dataGridView1.Columns[colToMove].DisplayIndex = colIndexOfItemUnderMouseToDrop;
// Select the column:
dataGridView1.Columns[colToMove].Selected = true;
}
}
}
EDIT
New approach:
private DataGridViewColumn columnToMove;
public Form1()
{
InitializeComponent();
dataGridView1.Columns.AddRange(new DataGridViewColumn[]
{
new DataGridViewTextBoxColumn { Name = "AAA", SortMode = DataGridViewColumnSortMode.NotSortable },
new DataGridViewTextBoxColumn { Name = "BBB", SortMode = DataGridViewColumnSortMode.NotSortable },
new DataGridViewTextBoxColumn { Name = "CCC", SortMode = DataGridViewColumnSortMode.NotSortable }
});
dataGridView1.Rows.Add(2);
dataGridView1.AllowUserToOrderColumns = true;
dataGridView1.MouseDown += dataGridView1_MouseDown;
dataGridView1.ColumnDisplayIndexChanged += dataGridView1_ColumnDisplayIndexChanged;
}
private void dataGridView1_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
{
if (e.Column == columnToMove)
{
dataGridView1.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect;
e.Column.Selected = true;
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
var hti = dataGridView1.HitTest(e.X, e.Y);
if (hti.Type == DataGridViewHitTestType.ColumnHeader)
{
columnToMove = dataGridView1.Columns[hti.ColumnIndex];
dataGridView1.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
}
}
I have a DataGridView, where I allow users to Drag/Drop rows to reorder them. This works fine, but it seems to be very sensitive - just clicking and moving the mouse slightly when clicking a cell starts the drag/drop operation.
So what I want to do is only allow dragging and dropping from the 'side bar' of the DataGridView - i.e. the 'column' to the left of the red line in the below image:
Is this possible? Here is my code:
[code]
private Rectangle dragBoxFromMouseDown;
private int rowIndexFromMouseDown;
private int rowIndexOfItemUnderMouseToDrop;
private void grdCons_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
if (dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(e.X, e.Y))
{
DragDropEffects dropEffect = grdCons.DoDragDrop(grdCons.Rows[rowIndexFromMouseDown], DragDropEffects.Move);
}
}
}
private void grdCons_MouseDown(object sender, MouseEventArgs e)
{
rowIndexFromMouseDown = grdCons.HitTest(e.X, e.Y).RowIndex;
if (rowIndexFromMouseDown != -1)
{
Size dragSize = SystemInformation.DragSize;
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
}
else
{
dragBoxFromMouseDown = Rectangle.Empty;
}
}
private void grdCons_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void grdCons_DragDrop(object sender, DragEventArgs e)
{
Point clientPoint = grdCons.PointToClient(new Point(e.X, e.Y));
rowIndexOfItemUnderMouseToDrop = grdCons.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
if (e.Effect == DragDropEffects.Move)
{
DataGridViewRow rowToMove = e.Data.GetData(typeof(DataGridViewRow)) as DataGridViewRow;
grdCons.Rows.RemoveAt(rowIndexFromMouseDown);
grdCons.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove);
}
}
[/code]
I managed to get Drag-and-Drop using only row headers working by checking the DataGridViewHitTestType in the MouseDown event handler like so:
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
// Get the index of the item the mouse is below.
rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;
// Here we also check that the HitTest happened on a RowHeader
if (rowIndexFromMouseDown != -1 && (dataGridView1.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.RowHeader))
{
// Remember the point where the mouse down occurred.
// The DragSize indicates the size that the mouse can move
// before a drag event should be started.
Size dragSize = SystemInformation.DragSize;
// Create a rectangle using the DragSize, with the mouse position being
// at the center of the rectangle.
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
e.Y - (dragSize.Height / 2)),
dragSize);
}
else
// Reset the rectangle if the mouse is not over an item in the ListBox.
dragBoxFromMouseDown = Rectangle.Empty;
}
I'm guessing that you got your code from the DataGridView FAQ since the code you have is almost identical to the example there?
If you didn't then I'd recommend having a look at the FAQ - it is filled with lots of good advice and examples.
I've DataGridView that bound a List<myClass> and i sort it by "Priority" property in "myClass".
So I want to drag an "DataGridViewRow" to certain position to change it's "Priority" property.
How could I "Drag & Drop" DataGridView Rows ?.
And how to handle this ?.
I found this code sample on MSDN
Note the following:
1). DataGridView property AllowDrop must be set to true (default is false).
2). The example below works out of the box when the DataGridView is NOT data-bound. Otherwise it will throw an InvalidOperationException. If it is databound, you should manipulate the order of items in the DataSource.
private Rectangle dragBoxFromMouseDown;
private int rowIndexFromMouseDown;
private int rowIndexOfItemUnderMouseToDrop;
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
// If the mouse moves outside the rectangle, start the drag.
if (dragBoxFromMouseDown != Rectangle.Empty &&
!dragBoxFromMouseDown.Contains(e.X, e.Y))
{
// Proceed with the drag and drop, passing in the list item.
DragDropEffects dropEffect = dataGridView1.DoDragDrop(
dataGridView1.Rows[rowIndexFromMouseDown],
DragDropEffects.Move);
}
}
}
private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
// Get the index of the item the mouse is below.
rowIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).RowIndex;
if (rowIndexFromMouseDown != -1)
{
// Remember the point where the mouse down occurred.
// The DragSize indicates the size that the mouse can move
// before a drag event should be started.
Size dragSize = SystemInformation.DragSize;
// Create a rectangle using the DragSize, with the mouse position being
// at the center of the rectangle.
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
e.Y - (dragSize.Height / 2)),
dragSize);
}
else
// Reset the rectangle if the mouse is not over an item in the ListBox.
dragBoxFromMouseDown = Rectangle.Empty;
}
private void dataGridView1_DragOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
// The mouse locations are relative to the screen, so they must be
// converted to client coordinates.
Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));
// Get the row index of the item the mouse is below.
rowIndexOfItemUnderMouseToDrop =
dataGridView1.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
// If the drag operation was a move then remove and insert the row.
if (e.Effect== DragDropEffects.Move)
{
DataGridViewRow rowToMove = e.Data.GetData(
typeof(DataGridViewRow)) as DataGridViewRow;
dataGridView1.Rows.RemoveAt(rowIndexFromMouseDown);
dataGridView1.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove);
}
}
The Answer from 'Wahid Bitar' helped me a lot. I cannot comment the above, so a small addition:
If deleting a row is unwanted as commented by 'neminem': Just add to DragDrop Event just before the lines that finally moves it:
if (rowIndexOfItemUnderMouseToDrop < 0 )
{
return;
}
dataGridView1.Rows.RemoveAt(rowIndexFromMouseDown);
dataGridView1.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove);