davioooh
davioooh

Reputation: 24706

WinForms DataGridView behaviour similar to SQL Server Management Studio

I'm working with DataGridViews 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

Answers (1)

David Hall
David Hall

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

Related Questions