views:

8201

answers:

3

Thanks in advance for any help.

I'm using VS 2008/C# and binding a local List of helper classes as the DataSource for a DataGridView control. Calling the Remove() method on my List of helper classes fires the CellFormatting event of the DataGridView, which makes sense (a bit). But for some reason, when removing whatever happens to be the DataBoundItem of the last row in the grid (so long as the grid has more than one row) the DataGridView's Rows collection is not updated before this event fires. So, in the CellFormatting event handler, I get an IndexOutOfRangeException as the Rows collection is one too large.

I've tried removing the row using the DataGridView.Rows.Remove() method, and binding using a BindingSource rather than binding the List directly as the data source, both to no avail.

I found a few references to this occurance via Google, but answers were either not forthcoming or said to use a Delete() method on either the DataGridView or the DataGridView.Rows collection - neither of which currently exist.

Sorting does not appear to be the issue either, as performing/not performing a sort results in the same outcome.

The only exception to the "last row" being a problem for removal is if the DataGridView contains only one row - in which case everything works fine.

Hopefully some readers have already tackled this issue and would be willing to help. Thanks again!

+6  A: 

I've had this problem in the past, and if I remember correctly there's one of two things you can do. When you remove the record from the collection, set the datasource property on your datagridview to null, and then rebind it to your list. That should do the trick.

Alternatively, you can handle the DataError event on your dataGridview and in the method you can say e.Cancel = true to suppress the exception, or you can further deal with it there.

BFree
setting to null and back to collection worked.
Pat
A: 

I don't have enough points to vote, but the answer BFree provided was the only way I was able to get it to work. I chose to set the datasource property to null and then rebind.

The only anomaly I ran into was that it only worked if I did this before the actual event on the underlying list.

dgvFees.DataSource = null;
dgvFees.DataSource = this.bindingFees;

//didn't matter which way I removed the object.
bindingFees.RemoveCurrent();
// dgvFees.Rows.Remove( dgvFees.CurrentRow );

However, I'm overriding AddNewCore() and RemoveItem( int index ) from an inherited base class, so maybe your mileage will differ.

codefoo
A: 

It is a very old problem, but i solved it by handling the row-remove event, as follows.

private void dgViewItems_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
{
     dataAdapter.Update((DataTable)bindingSource1.DataSource);
}

and it worked.

inam101