有人能告诉我一些代码,说明在按TAB键时我如何绕过DatagridView中的只读单元格?
答案 0 :(得分:13)
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.CurrentRow.Cells[e.ColumnIndex].ReadOnly)
{
SendKeys.Send("{tab}");
}
}
答案 1 :(得分:5)
覆盖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是否也有焦点。
答案 2 :(得分:3)
我做了一个继承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;
}
}
}
答案 3 :(得分:0)
继承DataGridView并覆盖ProcessDialogKey(对于编辑时按下的键)和ProcessDataGridViewKey(对于未编辑时按下的键)。按Tab键时,将CurrentCell设置为下一个非只读单元格。
可选择覆盖WndProc以过滤对只读单元格的鼠标点击。 (请参阅DataGridView.GetColumnDisplayRectangle以查找单击了哪个列。)
从here开始的良好来源。
答案 4 :(得分:0)
当单元格处于编辑模式,并且您想要听击键事件时,您可能会尝试处理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事件处理程序。
答案 5 :(得分:0)
赫克托耳 - 我希望你还在听。您的解决方案是我在广泛搜索中看到的最优雅,最直接的解决方案。我已经遇到了覆盖关键事件的建议,但是你调用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。 谢谢。史蒂夫
答案 6 :(得分:0)
您可以通过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
答案 7 :(得分:-1)
if (e.KeyValue == 13)
{
e = new KeyEventArgs(Keys.Tab);
}