Tip: Auto Scroll While Implementing Drag & Drop for Reordering Rows in DataGridView

There are tons of articles detailing how to re-order rows in a data grid (here is a good one) but none handle this nuance of allowing the user to scroll up and down while dragging a row to a point beyond the displayed rows on the screen.

The Problem

Say a form hosts a datagrid that was sized to display 10 rows, and the gridvew has 100 rows. If the user has scrolled down to a point where the gridview displays rows 30 to 40, and if the user wants to move the 35th row to the second position, the gridview by default doesn't scroll up when user drags row 25 beyond the row header (or beyond row 40). This can be very annoying.

The Solution

This solution, in just four lines of code, implements the scroll up and scroll down feature when user drags a row beyond the datagridview's top and bottom bounds. After implementing the code to do a drag and drop re-ordering, in the DragOver event handler, add the following lines (the code assumes you have a datagridvew object called dataGridView1.)

private void dataGridView1_DragOver(object sender, DragEventArgs e)
{
   e.Effect = DragDropEffects.Move;

   if (e.Y <= PointToScreen(new Point(dataGridView1.Location.X,
      dataGridView1.Location.Y)).Y+40)
      dataGridView1.FirstDisplayedScrollingRowIndex -= 1;
   if (e.Y >= PointToScreen(new Point(dataGridView1.Location.X+
      dataGridView1.Width, dataGridView1.Location.Y+
      dataGridView1.Height)).Y - 10)
   dataGridView1.FirstDisplayedScrollingRowIndex += 1;
}

Code Explained

Initially, I tried to handle this in the mouse move event when the LButton was down and the row index returned was equal to the datagridvew's FirstDisplayedScrollingRowIndex. But, this didn't work; when I used Debug.Write to trace the problem (because placing a break point in mouse move is next worst thing to HELL), I noticed that the move events were not fired when the LButton was down and after the cursor has moved out of the selected row (I assume that the do drag was eating away these events).

So, I changed my focus to the DragOver event handler. The code is pretty straightforward; it uses the following condition to check whether the user is dragging beyond the top visible row.

if (e.Y <= PointToScreen(new Point(dataGridView1.Location.X,
   dataGridView1.Location.Y)).Y+40)
Note: The PointToScreen conversion as dataGridView1.Location.X will give co-ordinates relative to the hosted form and e.Y gives co-ordinates relative to the screen.

I am adding an offset of 40 just to accommodate for the header size (someone can probably write bettor code by calculating the header hight). Once the condition is satisfied, just call the code to increment or decrement the datagridview's FirstDisplayedScrollingRowIndex.

Happy coding.



About the Author

Naveen Konduri

I am what I am and I am not what I am not

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • It's time high-level executives and IT compliance officers recognize and acknowledge the danger of malicious insiders, an increased attack surface and the potential for breaches caused by employee error or negligence. See why there is extra emphasis on insider threats.

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds