簡體   English   中英

[C#DataGridView]如何讓datagridview在單元格編輯后接收到keydown事件,而不是單元格控件

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

我有一個 KeyDown 事件,在 DataGridView 中,當按下回車鍵時,選擇移動到下一列而不是下一行。 我編寫的代碼僅在單元格未處於編輯模式時才有效。 當單元格是單元格結束編輯時,選擇移動到下一行同一列。 有人可以解釋我嗎?

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];
        }
    }

您描述的問題來自這樣一個事實,即當網格單元處於“編輯模式”時,它將是“單元控件”,當用戶按下鍵時會觸發其KeyDown事件。 這就是當單元格處於編輯模式時不會觸發“Grids” KeyDown事件的原因。

在大多數情況下,獲取單元格按鍵事件的策略是使用網格EditingControlShowing事件。 當單元格進入“編輯模式”時,將觸發此事件。 在這種情況下,我們會將網格單元格轉換為常規TextBox ,然后連接該文本框的KeyPress事件。 然后當用戶在單元格中輸入文本時,文本框KeyPress事件將觸發,我們可以檢查按下的鍵。 聽起來很有希望,但是有一個與您正在做的事情有關的問題……

當用戶按下“Enter”鍵時,文本框KeyPress事件不會觸發。

網格將立即“吞下” Enter 鍵並退出其編輯模式。 如果我們只是阻止用戶為僅數字單元格之類的內容輸入無效字符,這很好。 但是,在這種情況下,如果要“捕獲”“Enter”鍵,我們需要做其他事情。

鑒於此,我建議不要連接文本框KeyPress事件……我們連接文本框PreviewKeyDown事件。 當用戶按下一個鍵時觸發此事件,如果它是“Enter”鍵,它將在網格吞下它之前捕獲它。 這里的問題是我們無法在該事件中設置網格當前行而沒有問題。

但是,我們可以通過“Enter”鍵來了解用戶是否正在“離開”已編輯的單元格。 換句話說,如果用戶在“編輯模式”中按下“Enter”鍵,我們希望稍后在網格最終“離開”該編輯單元格時知道這一點。

這是網格CellEndEdit事件可能派上用場的地方。 當用戶嘗試“離開”已編輯的單元格時,將觸發此事件。 這意味着通過按 Tab 鍵、箭頭鍵甚至單擊另一個單元格來離開單元格。 在所有這些情況下,我們不想更改單元格的下一個位置。 但是……如果單元格因為用戶按下“回車”鍵而結束編輯……我們確實想更改下一個當前單元格。

因此,如果我們知道單元格結束編輯的原因是因為用戶按下了“Enter”鍵,那么……我們就會知道在下一個當前單元格中更改網格。 因此,一種方法可能是 go 之類的......

創建一個全局 boolean 變量並將其設置為 false ...

bool EndEditBecauseEnterPressed = false;

然后連接網格EditingControlShowing事件以獲取已編輯的單元格並連接其PreviewKeyDown事件。 這可能看起來像……

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);
  }
}

接下來,我們實現textbox_PreviewKeyDown事件。 它只做一件事……它尋找“Enter”鍵。 如果按下“Enter”鍵,我們只需將全局變量EndEditBecauseEnterPressed設置為true

我們知道,由於用戶按下“Enter”鍵,網格CellEndEdit將在接下來觸發,我們可以在那里檢查EndEditBecauseEnterPressed變量。 如果是真的,那么我們希望我們的代碼將當前單元格向右移動。

這兩個事件可能看起來像……

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;
  }
}

我希望這是有道理的並有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM