DataGridView SelectionChanged event behaves strange
In a project where I use the handy DataGridView control I, bind a data source to
a grid view, then listen for the SelectionChanged
event. When the event is fired,
I enable or disable other controls according to the data that is contained in the
grid. For instance, I disable a move down button if I have less than two items in
the list, or if the selected row is the last one.
However, the SelectionChanged
event behaves strange. It fires several times when
data is being bound and when the control is displayed. The last time it is fired,
the RowCount
property of the grid is 1, no matter how many rows it contains.
This makes my enable/disable functionality fail.
The bug(?) can be recreated as such:
- Add a DataGridView to a form
- Bind its
SelectionChanged
event and set a local int variable to its RowCount - Add a breakpoint to the SelectionChanged event, so it can be inspected
- In the form constructor, create a
List<String>
with several strings and bind it to the grid view. - Run the application
As you probably will see, the SelectionChanged
event fires several times. The
last time it fires, the grid is said to contain 1 row, although it has several.
Furthermore, the SelectionChanged
event also does not fire when the list goes
from containing none to containing one item, nor from containing one item to none.
I found the DataSourceChanged event to behave much more stable. It is fired every
time I modify the data source in any way. Also…it fires correctly. For the move
up/down functionality, I also need to listen for the CurrentCellChanged
event.
After some further issues with the SelectionChanged
event, I found that it also
applies to the CurrentCell property. If the control has not yet been displayed, the
property will be null.
Therefore, when you need to update the GUI according to a selection event in the DataGridView control, just follow this pattern:
- Create a function that enables and disabled your GUI controls correctly
- Create an event handler that executes this function
- Bind the event handler to the following events of the data grid view:
CurrentCellChanged
DataSourceChanged
VisibleChanged
This will hopefully make your GUI behave the way you want it to.