tags:

views:

169

answers:

1

I tried to bind List<T> to DataGridView. Everything seemed to be ok before I implemented deleting rows:

Companies.CompaniesList.RemoveAt(dataGridView1.SelectedRows[0].Index);
dataGridView1.DataSource = Companies.CompaniesList;

(Companies.Companies is List<Company> collection) What I've got is data error message (although row was deleted successfully). I tried this:

Companies.CompaniesList.RemoveAt(dataGridView1.SelectedRows[0].Index);
bs = new BindingSource();
bs.DataSource = Companies.CompaniesList;
dataGridView1.DataSource = bs;

It works as expected. The question is: why?

+6  A: 

It is common for property changes (via set) to detect and ignore changes that do nothing, so in the line:

dataGridView1.DataSource = Companies.CompaniesList;

I expect that DataSource is already Companies.CompaniesList, so nothing happened. No code executed except to test the reference. Checking in reflector confirms this (DataGridView.DataSource):

set
{
    if (value != this.DataSource)
    {
        ...
    }
}

So it only does anything when the reference is updated.

Additionally, since List<T> doesn't implement the necessary binding interfaces, the grid has no idea that the list contents have been changed, hence the error. Now contrast:

bs = new BindingSource();
bs.DataSource = Companies.CompaniesList;
dataGridView1.DataSource = bs;

Here, the DataSource has changed, as bs is an entirely new object. This causes the entire grid to rebind.

Another option is to use BindingList<T>, or to remove from the BindingSource (rather than the List<T>) which should operate in both directions.

Marc Gravell
Thank you! This is a great answer.
Sergey