BindingList(Of T).Items.Clear and BindingList(Of T).ClearItems are NOT the same thing

I got an email this evening from alert reader Teddy Garcia telling me there was a bug in the 2.0 version of the StudentCollection class that shipped with my MSDN article.  My first instinct was that he had to be mistaken because I of course am above simple coding errors. :-)  But sadly he was not mistaken and I am in fact fallable.

The problem is in the ResetList method.  This method  clears out the current list of items and replaces it with the newly sorted list.  However, in the source code I was clearing the list by calling Me.Items.Clear().  While that would seem like the correct thing to do, this will cause an IndexOutOfRangeException when the DataGridView tries to display the sorted list.  The reason is that the DataGridView never received notification that the original records were removed from the list, but when I call the Add() method the DataGridView does receive notification of the new rows being added.  This in turn causes the DataGridView to think there are more rows in the collection than there really are and hence the IndexOutOfRangeException.

The solution to this is to call the BindingList(Of T).ClearItems() method instead of  BindingList(Of T).Items.Clear().  This method calls the internal list's Clear method and then raises the ListChanged event which is what the DataGridView needs to keep everything in sync.

I did a little bit more research and found that the BindingList(Of T) class has several methods implemented to ensure that the ListChanged event gets fired when the internal list changes including InsertItem, RemoveItem, and ResetItem.  This got me curious though as to why there was no AddItem.  So through the miracle that is Lutz Roeder's Reflector Tool, I looked at the IL for the BindingList(Of T) class and saw that it's base class (Collection(Of T)) implements the Add method by finding the last element in the list and then calling the virtual InsertItem method which for the BindingList(Of T) also fires the ListChangedEvent.  Ah, the joys of object oriented programming.

I have updated the source code to include this fix.  Much thanks to Teddy for sniffing this out for me.  You can download the file (ZIP) here.

 

No Comments