繁体   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