November 2019

The datagridview is windows forms' main method of showing a list, but sometimes it can be a little hard to tame.

Keep the selected row when refreshing the list

You commonly need to redisplay the list, like if some of the rows have changed. But the silly thing unselects the row each time.

First, remember the selected row. I store the primary key from the database in the tag of each row for other purposes, so let's just remember which primary key was selected.

Remember the selected row
string SelectedRow = "xyzzy";
if (dataGridView1.SelectedRows.Count > 0)
	DataGridViewRow TheRow = dataGridView1.SelectedRows[0]; 
	if (TheRow != null)
		SelectedRow = TheRow.Tag.ToString();

First, look to see if any rows are selected. If so, grab the first DataGridViewRow from the selected rows list. The tag of that row is the one you want to save. I used "xyzzy" to indicate NO selected row.

A datagridview can have more than one row selected. In this case, I wasn't worried about that, but if it applies to you, you'll want to use a dictionary to store the rows instead of a string. Loop through the SelectedRows list adding their tags to this dictionary.

Clear the row list of the datagridview

And reload them by whatever method is convenient. When I add the row to the list, I check the tag. If the tag matches the saved tag, set the Selected property to true.

Add the row and select if in the list
if (rd["TestTitlePK"].ToString().Equals(SelectedRowTag)) dataGridView1.Rows[rw].Selected = true;

Keep list from scrolling to top on refresh

The datagridview Annoyingly scrolls to the top each time you reload the rows. This is pretty easy to solve using the handy property with the cumbersome name of "FirstDisplayedScrollingRowIndex." Just save it before you clear the rows, and restore it after.

Remember the scroll position
int FirstRow = dataGridView1.FirstDisplayedScrollingRowIndex;
 ... load the datagridview rows ...
if (FirstRow > -1 ) dataGridView1.FirstDisplayedScrollingRowIndex = FirstRow;

Select the row and show context menu on right click.

This too was hard to find how to do, but pretty easy.

First, use the Mouse Up Event.

private void dataGridView1_MouseUp(object sender, MouseEventArgs e)
	if (e.Button != MouseButtons.Right) return; 

	int RowIndex = dataGridView1.HitTest(e.X, e.Y).RowIndex;
	if (RowIndex < 0) return;
	dataGridView1.Rows[RowIndex].Selected = true;

	ContextMenuStrip cms = new ContextMenuStrip();
	cms.BackColor = Color.Black;
	cms.ForeColor = Color.Yellow;
	cms.GripStyle = ToolStripGripStyle.Visible;
	cms.Items.Add("Tellus porta", Properties.Resources.clip, IncludeRow);
	cms.Items.Add("Gravida iaculis", Properties.Resources.blank, ExcludeRow);
	cms.Show(dataGridView1, new Point(e.X, e.Y));

You see I used the "HitTest" method to find which row was right clicked and set the Selected attribute of that row.

You don't have to build the context menu strip in code this way, it was just convenient to show. You show a menu strip using the show method. I specified the datagridview and a point given the x and y positions from the eventargs. This gets the context menu strip to show at the clicked location so your user isn't lost and confused.