Search code examples
c#winformsdatagridviewcancellation

CancelEdit after Programmatic value change to a DataGridViewCell does not work


Code snippets from minimal problematic example:

private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.DataGridViewTextBoxColumn colButtonEditedText;
private System.Windows.Forms.DataGridViewButtonColumn ColBrowse;
private System.Windows.Forms.DataGridViewTextBoxColumn colOtherText;


this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
        this.colButtonEditedText,
        this.ColBrowse,
        this.colOtherText});


this.dataGridView1.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellClick);


private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex >= 0 && e.ColumnIndex >= 0
            && dataGridView1.Columns[e.ColumnIndex].GetType() == typeof(DataGridViewButtonColumn))
    {
            dataGridView1.NotifyCurrentCellDirty(true); // needed to make new row appear
            dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex - 1].Value
                = "some value"; // button helps user edit row
    }
}

Observed Behavior:

  1. Type a character in first column.
  2. Press escape.
    Observe: Row you just added is canceled.
  3. Press the button.
    Observe: first column is edited.
  4. Press escape.
    Observe: Row remains in edit mode and is not canceled.
  5. Type a character in the last column of the same row.
  6. Press escape.
    Observe: Row you just added is canceled, both edits go away.

How do I make the behavior after step 4 to be the same as after step 2 & 6?

Things I've tried:

dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex - 1].Selected = true;
dataGridView1.BeginEdit(true);
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.LeaveControl);
dataGridView1.EndEdit();

Solution

  • The reason you're seeing this behavior has something to do with which Control has focus. Clicking on a Button cell removes this focus from the DataGridView, thus preventing the CancelEdit from triggering as expected. Within your if-statement, try the following:

    dataGridView1.NotifyCurrentCellDirty(true);
    dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex - 1];
    dataGridView1.BeginEdit(false);                
    dataGridView1.EditingControl.Text = "some value";
    

    It may seem a little hacky since you are changing focus from the Button cell to the edited cell, but when you hit Esc you'll see the desired behavior.


    Sidenote: I'd handle the DataGridView.CellContentClick event instead - only triggers if the Button itself gets clicked instead of the whole cell.