Monday 29 February 2016

c# - DataGridView System.InvalidOperationException Cell is not in a DataGridView



For the first time in a while, I can find no use information on this exception on Google... hoping someone else may have come across it.




I have a DataGridView that I validate for empty cells on the Leave event and remove those rows.



If I leave the last cell empty in the last row and tab away from the DGV the following exception is thrown:




System.InvalidOperationException: Cell is not in a DataGridView. The
cell cannot retrieve the inherited cell style.




I am not using Data Binding and a if I place a Breakpoint at this.dataGridView1.Rows.RemoveAt(c.RowIndex); It is hit and if if I step into this line the exception is thrown during the execution of non-user code...




I had thought this was to do with Uncommitted Changed but it seems explicitly committing the changes does not affect the outcome.



My Leave Event code:



    private void dataGridView1_Leave(object sender, EventArgs e)
{

if (this.dataGridView1.IsCurrentRowDirty || this.dataGridView1.IsCurrentCellDirty) this.dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);


//Validate for empty rows
foreach(DataGridViewRow row in this.dataGridView1.Rows)
{

foreach(DataGridViewCell c in row.Cells)
{

if(c.Value == null || c.Value.ToString() == String.Empty)
{
if (c.EditedFormattedValue == null || c.EditedFormattedValue.ToString() == "")

{
this.dataGridView1.Rows.RemoveAt(c.RowIndex);
break;
}

}
}


}

}


Exception Data is here:



System.InvalidOperationException: Cell is not in a DataGridView. The cell cannot retrieve the inherited cell style.
at System.Windows.Forms.DataGridViewCell.GetInheritedStyle(DataGridViewCellStyle inheritedCellStyle, Int32 rowIndex, Boolean includeColors)
at System.Windows.Forms.DataGridView.OnCellValidating(DataGridViewCell& dataGridViewCell, Int32 columnIndex, Int32 rowIndex, DataGridViewDataErrorContexts context)
at System.Windows.Forms.DataGridView.CommitEdit(DataGridViewCell& dataGridViewCurrentCell, DataGridViewDataErrorContexts context, DataGridViewValidateCellInternal validateCell, Boolean fireCellLeave, Boolean fireCellEnter, Boolean fireRowLeave, Boolean fireRowEnter, Boolean fireLeave)
at System.Windows.Forms.DataGridView.EndEdit(DataGridViewDataErrorContexts context, DataGridViewValidateCellInternal validateCell, Boolean fireCellLeave, Boolean fireCellEnter, Boolean fireRowLeave, Boolean fireRowEnter, Boolean fireLeave, Boolean keepFocus, Boolean resetCurrentCell, Boolean resetAnchorCell)

at System.Windows.Forms.DataGridView.ProcessDialogKey(Keys keyData)
at System.Windows.Forms.Control.ProcessDialogKey(Keys keyData)
at System.Windows.Forms.TextBoxBase.ProcessDialogKey(Keys keyData)
at System.Windows.Forms.Control.PreProcessMessage(Message& msg)
at System.Windows.Forms.Control.PreProcessControlMessageInternal(Control target, Message& msg)
at System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(MSG& msg)
at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FPreTranslateMessage(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.Run(Form mainForm)

Answer



If you're using foreach-loop, you can't remove items from the collection it's using. Here you're removing items from this.dataGridView1.Rows.



Try this:



for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
DataGridViewRow row = dataGridView1.Rows[i];


for (int k = 0; k < row.Cells.Count; k++)
{
DataGridViewCell c = row.Cells[k];

if (c.Value == null || c.Value.ToString() == String.Empty)
{
if (c.EditedFormattedValue == null || c.EditedFormattedValue.ToString() == "")
{
this.dataGridView1.Rows.RemoveAt(c.RowIndex);


// Decrease i, as the collection got smaller
i--;
break;
}

}
}
}


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...