按TAB键时,绕过DataGridView中的只读单元格

任何人都可以给我看一些代码,告诉我如何在按TAB键时绕过DatagridView中的只读单元格?

覆盖SelectionChanged事件是正确的方法。 CurrentCell属性可用于设置当前单元格。 你想要这样的东西:

private void dataGridView_SelectionChanged(object sender, EventArgs e) { DataGridViewCell currentCell = dataGridView.CurrentCell; if (currentCell != null) { int nextRow = currentCell.RowIndex; int nextCol = currentCell.ColumnIndex + 1; if (nextCol == dataGridView.ColumnCount) { nextCol = 0; nextRow++; } if (nextRow == dataGridView.RowCount) { nextRow = 0; } DataGridViewCell nextCell = dataGridView.Rows[nextRow].Cells[nextCol]; if (nextCell != null && nextCell.Visible) { dataGridView.CurrentCell = nextCell; } } } 

您需要为当前正在读取的单元格添加测试并循环,而下一个单元格不可见或只读。 如果所有单元格都是只读的,您还需要检查以确保不会循环。

您将不得不应对显示索引与基本索引不同的情况。

要在按Tab键时获得此行为,您需要添加KeyDown处理程序:

 private void AlbumChecker_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Tab) { SelectNextEditableCell(DataGridView dataGridView); } } 

并将第一个代码放在这个新方法中。

您可能想要检查DataGridView是否也具有焦点。

 private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e) { if (dataGridView1.CurrentRow.Cells[e.ColumnIndex].ReadOnly) { SendKeys.Send("{tab}"); } } 

我做了一个inheritanceDataGridView类的例子。 该示例适用于TAB和ENTER键,因此用户可以快速插入数据,但仍然可以使用鼠标或上,下,右,左键选择单元格并将其复制到Excel。 它可以模拟几个TAB,直到Grid进入非ReadOnly Cell。 希望它有用。

 using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; namespace System.Windows.Forms { class MyDataGridView : DataGridView { protected override bool ProcessDialogKey(Keys keyData) { if (keyData == Keys.Enter || keyData == Keys.Tab) { MyProcessTabKey(Keys.Tab); return true; } return base.ProcessDialogKey(keyData); } protected override bool ProcessDataGridViewKey(KeyEventArgs e) { if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab) { MyProcessTabKey(Keys.Tab); return true; } return base.ProcessDataGridViewKey(e); } protected bool MyProcessTabKey(Keys keyData) { bool retValue = base.ProcessTabKey(Keys.Tab); while (this.CurrentCell.ReadOnly) { retValue = base.ProcessTabKey(Keys.Tab); } return retValue; } } } 

inheritanceDataGridView并覆盖ProcessDialogKey(对于编辑时按下的键)和ProcessDataGridViewKey(对于未编辑时按下的键)。 按Tab键时,将CurrentCell设置为下一个非只读单元格。

(可选)覆盖WndProc以过滤对只读单元格的鼠标单击。 (请参阅DataGridView.GetColumnDisplayRectangle以查找单击了哪个列)。

从这里开始的好来源。

当单元格处于编辑模式,并且您想要听击键事件时,您可能会尝试处理DataGridView的EditingControlShowing事件……

 Private Sub myDvGrid_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles myDvGrid.EditingControlShowing Dim c As DataGridViewTextBoxEditingControl = DirectCast(e.Control, DataGridViewTextBoxEditingControl) RemoveHandler c.PreviewKeyDown, AddressOf edtctrlOn_PreviewKeyDown RemoveHandler c.TextChanged, AddressOf edtctrlOn_TextChanged AddHandler c.TextChanged, AddressOf edtctrlOn_TextChanged AddHandler c.PreviewKeyDown, AddressOf edtctrlOn_PreviewKeyDown End Sub 

然后,在edtctrlOn_PreviewKeyDown事件中,您可以将参数冒泡到原始datagrid的PreviewKeyDown事件处理程序。

赫克托耳 – 我希望你还在听。 您的解决方案是我在广泛搜索中看到的最优雅,最直接的解决方案。 我已经遇到了覆盖关键事件的建议,但是你调用base.ProcessTabKey的建议特别简单,当你到达dgv的末尾时它处理焦点传递给下一个控件。 您的解决方案需要的另一件事是在MyProcessTabKey中检查dgv的最后一个单元格。 如果该单元格是只读的并且用户在前一个单元格中进行选项卡,则while语句将进入无限循环。 添加以下代码作为while循环中的第一个语句似乎可以解决问题,尽管它确实将最后一个(只读)单元格保留为“活动”单元格(意味着它看起来好像已被选中)。

  if (this.CurrentCell.RowIndex == this.Rows.Count - 1 && this.CurrentCell.ColumnIndex == this.Columns.Count - 1) { retValue = false; break; } 

我有一个后续问题。 你或其他任何人都知道如何使这种方法与Shift-Tab一起使用,所以dgv也会向后跳过只读单元格吗? 由于Shift和Tab是不同的键事件,我不知道如何在重写的ProcessDialogKey和ProcessDataGridViewKey方法中检测Shift-Tab。 谢谢。 史蒂夫

您可以在ProcessDialogKey中通过此代码捕获Tab键

  Dim uKeyCode As Keys = (keyData And Keys.KeyCode) Dim uModifiers As Keys = (keyData And Keys.Modifiers) (uKeyCode = Keys.Return OrElse uKeyCode = Keys.Tab) AndAlso uModifiers = Keys.Shift 

并通过ProcessDataGridViewKey中的此代码

  (e.KeyCode = Keys.Return OrElse e.KeyCode = Keys.Tab) AndAlso e.Modifiers = Keys.Shift 
  if (e.KeyValue == 13) { e = new KeyEventArgs(Keys.Tab); }