【发布时间】:2009-04-15 14:32:17
【问题描述】:
谁能告诉我一些代码,说明我在按 TAB 键时如何绕过 DatagridView 中的只读单元格?
【问题讨论】:
-
看看我的回答stackoverflow.com/a/71000393/3892975这是完美的解决方案。
标签: c# winforms datagridview
谁能告诉我一些代码,说明我在按 TAB 键时如何绕过 DatagridView 中的只读单元格?
【问题讨论】:
标签: c# winforms datagridview
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.CurrentRow.Cells[e.ColumnIndex].ReadOnly)
{
SendKeys.Send("{tab}");
}
}
【讨论】:
覆盖 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 是否也有焦点。
【讨论】:
我做了一个继承DataGridView 类的例子。该示例适用于 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;
}
}
}
【讨论】:
继承 DataGridView 并覆盖 ProcessDialogKey(对于在编辑时按下的键)和 ProcessDataGridViewKey(对于在不编辑时按下的键)。按下 Tab 时,将 CurrentCell 设置为下一个非只读单元格。
选择性地覆盖 WndProc 以过滤只读单元格上的鼠标点击。 (请参阅 DataGridView.GetColumnDisplayRectangle 以查找单击了哪一列)。
从here开始的好来源。
【讨论】:
当单元格处于编辑模式,并且您想监听击键事件时,您可以尝试处理 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 事件中,您可以将参数冒泡到原始数据网格的 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);
}
【讨论】: