Julie's Journal

Reflections on my journey through life + some (hopefully) useful info

Keep focus with current row if changing cell value causes sort in a data bound DataGridView

When a DataGridView has been set to sort, changing a cell’s contents can cause the current row to be moved if that cell is in a sorted column in the DataGridView.

In my specific case, the DataGridViewhas been set to sort on multiple columns by setting the Sort property on the BindingSource.

To ensure that focus remains with the current row, even if that row is moved due to it being sorted to a new position, handle the BindingSource.ListChanged event for ListChangedType.ItemMoved.

For example,

void bindingSource_ListChanged(object sender, ListChangedEventArgs e)
{    
    if (e.ListChangedType == ListChangedType.ItemMoved)
    {    
        // Focus follows program entry
        bindingSource.Position = e.NewIndex;
    }
}

This method works well when changing existing rows, however when the user enters a new row that is moved (due to the sort when the user clicks Save), the focus is moved to the row AFTER the new row’s new position. I suspect that this is due to some built-in behaviour of the DGV whereby it places the cursor on the row after the ‘New’ row when the user clicks save

A graphic example;

  1. DGV has 5 rows, sorted on the first column. Row values are A, B, D, E, F
  2. Click [+] to add a new row
  3. Enter ‘C’ in the first cell of the new row
  4. Click [Save]
  5. The new row is inserted (as expected) between the B and D rows
  6. Set .Position = e.NewIndex in the ListChanged event handler
  7. The cursor is placed on the D row

Interestingly, in step 6, setting .Position = e.NewIndex-1 still results in the cursor being placed on the D row.

By logging the sequence of events, it appears that the new row is moved into the new position on the DataGridView row BEFORE the row’s position is updated in the BindingSource.
i.e. The RowEnter event on the DataGridView is firing, and logging the value at that row shows the new value. Then a few milliseconds later, the BindingSource fires the ListChanged event with ListChangedType = ItemMoved and then the PositionChanged event fires indicating that it is now on the row after the new row’s new position.

This seems weird, since it is the BindingSource that is doing the sorting

I haven’t yet found a solution to this …

Sat 01 May 2010 Posted by | Programming, Technical | , , | Leave a comment