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

时间:2009-04-15 14:32:17

标签: c# datagridview

有人能告诉我一些代码,说明在按TAB键时我如何绕过DatagridView中的只读单元格?

8 个答案:

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