简体   繁体   中英

[C# DataGridView]How to make the datagridview receive the keydown event, not the cell control, after the cell edit

I have a KeyDown event in which in DataGridView, when pressed enter key, selection moves to next column and not the next row. The code I have written only works when the cells are not in edit mode. When the cells are cell end edit, selection moves to next row same column. Can someone explains me?

private void dataGridView_voucherdetail_KeyDown(object sender, KeyEventArgs e)
    {
        e.SuppressKeyPress = true;
        if (e.KeyData == Keys.Enter)
        {
            int iCol = dataGridView_voucherdetail.CurrentCell.ColumnIndex;
            int iRow = dataGridView_voucherdetail.CurrentCell.RowIndex;

            if (iCol < dataGridView_voucherdetail.Columns.Count - 1)
            {
                iCol = iCol + 1;
            }
            else if (iCol == dataGridView_voucherdetail.Columns.Count - 1 && iRow < dataGridView_voucherdetail.Rows.Count - 1)
            {
                iCol = 0;
                iRow = iRow + 1;
            }

            dataGridView_voucherdetail.CurrentCell = dataGridView_voucherdetail[iCol, iRow];
        }
    }

The issue you describe is coming from the fact the when a grids cell is in “Edit Mode”, it will be the “cell control” that has its KeyDown event triggered when the user presses keys. This is why the “Grids” KeyDown event is not firing when a cell is in edit mode.

In most cases, the strategy to get a cells key press event is to use the grids EditingControlShowing event. This event will fire when a cell goes into “Edit Mode.” In the event, we would cast the grid cell to a regular TextBox , then wire up that text boxes KeyPress event. Then as the user types text into the cell, the text boxes KeyPress event will fire and we can examine the pressed keys. Sounds promising, however there is one issue in relation to what you are doing…

The text boxes KeyPress event will NOT fire when the user presses the “Enter” key.

The grid will “swallow” the Enter key immediately and exit its edit mode. If we are simply preventing the user from entering invalid characters for something like a number only cell, this is fine. However, in this case where want to “capture” the “Enter” key, we need to do something else.

Given this, I suggest that instead of wiring up the text boxes KeyPress event… we wire up the text boxes PreviewKeyDown event. This event fires when the user presses a key AND it will capture it BEFORE the grid swallows it if it is the “Enter” key. Problem here is that we can not set the grids current row inside that event without problems.

However, we CAN look for the “Enter” key to know if the user is “leaving” the edited cell. In other words, if the user presses the "Enter" key while in “Edit Mode” we want to know this later when the grid eventually “leaves” that edited cell.

This is where the grids CellEndEdit event may come in handy. This event will fire when the user tries to “leave” an edited cell. This means leaving the cell by pressing the Tab key, arrow keys or even clicking on another cell. In all those cases, we do NOT want to change the cells next location. BUT… if the cell is ending its edit because the user pressed the “enter” key… we DO want to change the next current cell.

Therefore, if we knew that the reason the cell was ending its edit is because the user pressed the “Enter” key, then… we would know to change the grids next current cell. So, one way to do this may go something like…

Create a global boolean variable and set it to false …

bool EndEditBecauseEnterPressed = false;

Then wire up the grids EditingControlShowing event to grab the edited cell and wire up its PreviewKeyDown event. This may look like…

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  TextBox editedTB = e.Control as TextBox;
  if (editedTB != null) {
    editedTB.PreviewKeyDown -= new PreviewKeyDownEventHandler(textBox_PreviewKeyDown);
    editedTB.PreviewKeyDown += new PreviewKeyDownEventHandler(textBox_PreviewKeyDown);
  }
}

Next, we implement the textbox_PreviewKeyDown event. It does ONLY one thing… it looks for the “Enter” key. If the “Enter” key is pressed, them we simply set our global variable EndEditBecauseEnterPressed to true .

We KNOW that since the user pressed the “Enter” key that the grids CellEndEdit will fire next and it is there where we can check the EndEditBecauseEnterPressed variable. If it is true, then we want our code to move the current cell to the right.

These two events may look something like…

private void textBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
  if (e.KeyCode == Keys.Enter) {
    EndEditBecauseEnterPressed = true;
  }
}


private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
  if (EndEditBecauseEnterPressed) {
    if (dataGridView1.CurrentCell.ColumnIndex == dataGridView1.Columns.Count - 1) {
      if (dataGridView1.CurrentCell.RowIndex < dataGridView1.Rows.Count - 1) {
        dataGridView1.CurrentCell = dataGridView1[0, dataGridView1.CurrentCell.RowIndex + 1];
      }
    }
    else {
      if (dataGridView1.CurrentCell.RowIndex < dataGridView1.Rows.Count - 1) {
        SendKeys.Send("{up}");
      }
      dataGridView1.CurrentCell = dataGridView1[dataGridView1.CurrentCell.ColumnIndex + 1, dataGridView1.CurrentCell.RowIndex];
    }
    EndEditBecauseEnterPressed = false;
  }
}

I hope this makes sense and helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM