Reputation: 24706
I'm working with DataGridView
s in a Windows Form project.
I'd like to obtain something similar to what appens, in edit mode, in MS SQL Server Management Studio.
I try to explain: I've some mandatory columns in my datagrid and I'd like a row is added to the grid only if the values in these columns are valid. If the value of a cell is not valid I'd like to warn the user with a message box and pressing ESC, the incorrect row should be resetted.
I tried using CellValidating
and RowValidating
events, but I'm not satisfied of the result.
Can you help me?
UPDATE
I implemented RowValidating
this way:
private void myGrid_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
{
if (string.IsNullOrEmpty(myGrid.Rows[e.RowIndex].Cells["MandatoryColumn"].FormattedValue.ToString()))
{
e.Cancel = true;
myGrid.Rows[e.RowIndex].Cells["MandatoryColumn"].ErrorText = "Mandatory";
MessageBox.Show("Error message");
}
else
{
myGrid.Rows[e.RowIndex].Cells["MandatoryColumn"].ErrorText = string.Empty;
}
}
When the value in the mandatory field is not valid the message box is shown and the cell is red-dotted, but pressing ESC I obtain a IndexOutOfRangeException
...
The exception is thrown only if I show the message box, commenting it the method works (but that's not the behaviour I want to achieve...)
Upvotes: 4
Views: 969
Reputation: 33173
This issue is explained in the following MSDN forums post: DataGridView + RowValidating = Index 4 does not have a value?
Basically it appears to be a bug (or at least very unexpected behaviour) in the way the DataGridView handles validation - the MessageBox.Show() causing validation on a row that no longer exists.
I found that the following change to your code fixes the issue:
private void myGrid_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
{
// Note the check to see if the current row is dirty
if (string.IsNullOrEmpty(myGrid.Rows[e.RowIndex].Cells["MandatoryColumn"].FormattedValue.ToString()) && myGrid.IsCurrentRowDirty)
{
e.Cancel = true;
myGrid.Rows[e.RowIndex].Cells["MandatoryColumn"].ErrorText = "Mandatory";
MessageBox.Show("Error message");
}
else
{
myGrid.Rows[e.RowIndex].Cells["MandatoryColumn"].ErrorText = string.Empty;
}
}
The change is to check that the row being validated is dirty - when you press escape and remove a row it is no longer dirty so this prevents incorrectly trying to edit it.
Upvotes: 1