After all of this, things went along fairly smoothly in sample applications. Then I plugged it into my real application and scratched my head as I started getting errors about the rowIndex being out of range (ArgumentOutOfRangeException) even though the DataGridView had 5 elements, and the rowIndex being passed in was 0. It turns out this was happening whenever I would check the Value of the cell because the RowIndex was set to -1. This led me to the .NET documentation which talked about the concept of shared rows for the DataGridView. The one sentence summary on shared rows is that they are used in a DataGridView to ease memory use for a bunch of rows that are very similar. There are all sorts of internal rules that determine whether a row can be shared or not, but the long and short of it is that my DataGridView was using shared rows, as was evident from the RowIndex property being set to -1. Since the samples don't take this into account, I changed the code, and now everything is working fine. You can download my modified class to see how I made things work. If you have any feedback on this code, please feel free to leave a comment.
Other references:
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.