2

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 */
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Perfection
  • 721
  • 4
  • 12
  • 36
  • 1
    The data which you are trying to drop is not of type 'DataRowView'. If you have the source, inspect the 'if(e.Data.GetDataPresent(typeof(DataRowView)))' and see what is the type of data being dropped. Eg: It may be text data in which case the type is System.String – prthrokz Jan 07 '13 at 16:09
  • This is what the object contains. http://daven.nl/c/img/so-datagridviewrow.jpg It is a datagridviewrow... – Perfection Jan 08 '13 at 08:41
  • I am so confused, rebuilding fixed the application partially. – Perfection Jan 08 '13 at 09:31
  • Linked to: http://stackoverflow.com/questions/1620947/how-could-i-drag-and-drop-datagridview-rows-under-each-other – boctulus Dec 26 '14 at 02:41

2 Answers2

4

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");
        }
    }
Perfection
  • 721
  • 4
  • 12
  • 36
3

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);
        }
    }
}
Alejandro del Río
  • 3,966
  • 3
  • 33
  • 31
  • I believe the code under "//if shift key is not pressed" is designed to permit auto multiselect. It does not appear to work as intended. Removing (or leaving it in!) still provides a viable drag/drop mechanism. – JFish222 Jan 04 '14 at 03:12
  • @JFish222 If you press shift you may want to select all the rows from the previously selected to the one under the mouse. If you dont put this restriction all the previously selected rows will be unselected.Try it. – Alejandro del Río Jan 05 '14 at 14:59
  • Love those edge cases! :) Ok, so [test 1 - unmodified code]: I have rows 1-2 highlighted (ctrl-click). I shift+click row 5. Rows 2-5 are now highlighted. [test 2 - unmodified code]: I have rows 1-2 highlighted (SHIFT-click). I shift+click row 5. Rows 1-5 are now highlighted. Repeated test removing if statement. Behavior unchanged. Am I having a brain fart here? If you'd like to switch this over to a chat lmk. Thanks. – JFish222 Jan 06 '14 at 18:35