I found out that I got a race condition. I then checked the stacktrace:
- MyGridView.OnCellValueNeeded(System.Windows.Forms.DataGridViewCellValueEventArgs e)
- System.Windows.Forms.DataGridView.OnCellValueNeeded(int columnIndex, int rowIndex)
- System.Windows.Forms.DataGridViewCell.GetValue(int rowIndex)
- DataGridViewControlCell
- System.Windows.Forms.DataGridView.OnCellValidating(ref System.Windows.Forms.DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, System.Windows.Forms.DataGridViewDataErrorContexts context)
- System.Windows.Forms.DataGridView.CommitEdit(ref System.Windows.Forms.DataGridViewCell dataGridViewCurrentCell, System.Windows.Forms.DataGridViewDataErrorContexts context, System.Windows.Forms.DataGridView.DataGridViewValidateCellInternal validateCell, bool fireCellLeave, bool fireCellEnter, bool fireRowLeave, bool fireRowEnter, bool fireLeave)
- System.Windows.Forms.DataGridView.CommitEdit(System.Windows.Forms.DataGridViewDataErrorContexts context, bool forCurrentCellChange, bool forCurrentRowChange)
So it tried getting the value for the cell that was currently being edited !
I fixed it in MyGridView (called with base.OnCellValueNeeded):
protected override void OnCellValueNeeded(DataGridViewCellValueEventArgs e)
{
if (Columns[e.ColumnIndex] is DataGridViewControlColumn)
{
/*
* Special check to prevent race condition. Call this method first like this:
* base.OnCellValueNeeded(e);
* if (e.Value != null) return;
*/
if (Rows[e.RowIndex].Cells[e.ColumnIndex].IsInEditMode) // editing control present?
{
if ((EditingControl as TControl).EditingControlRowIndex == e.RowIndex) // make sure it's the correct row
{
if ((EditingControl as TControl).EditingControlValueChanged) // prevent re-use of old editing control
{
e.Value = (EditingControl as TControl).EditingControlFormattedValue; // use value from editing control
return;
}
}
}
}
base.OnCellValueNeeded(e);
}
{
if (Columns[e.ColumnIndex] is DataGridViewControlColumn
{
/*
* Special check to prevent race condition. Call this method first like this:
* base.OnCellValueNeeded(e);
* if (e.Value != null) return;
*/
if (Rows[e.RowIndex].Cells[e.ColumnIndex].IsInEditMode) // editing control present?
{
if ((EditingControl as TControl).EditingControlRowIndex == e.RowIndex) // make sure it's the correct row
{
if ((EditingControl as TControl).EditingControlValueChanged) // prevent re-use of old editing control
{
e.Value = (EditingControl as TControl).EditingControlFormattedValue; // use value from editing control
return;
}
}
}
}
base.OnCellValueNeeded(e);
}
Hopefully, you find this a bit useful.