如何在按下Enter键时将焦点移动到DataGridView中的下一个单元格

13

各位好,我正在使用 C# 开发 Windows 应用程序。我正在使用一个 datagridview 来显示记录。我需要的功能是当我按下 "Enter" 键时,焦点应该转移到下一个单元格(同一行的列)。如果它是网格中的最后一列,则焦点应该转移到下一行的第一列。我已经尝试过使用

    SendKeys.Send("{Tab}")

在datagridview1_KeyDown和datagridview1_KeyPress事件中,但焦点会对角线向下移动。请帮我解决这个问题。

6个回答

14
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    e.SuppressKeyPress = true;
    int iColumn = dataGridView1.CurrentCell.ColumnIndex;
    int iRow = dataGridView1.CurrentCell.RowIndex;
    if (iColumn == dataGridView1.Columncount-1)
    {
        if (dataGridView1.RowCount > (iRow + 1))
        {
            dataGridView1.CurrentCell = dataGridView1[1, iRow + 1];
        }
        else
        {
            //focus next control
        }
    }
    else
        dataGridView1.CurrentCell = dataGridView1[iColumn + 1, iRow];
}

1
它能工作,但不是100%。第一次填充网格后,我选择第一个单元格。然后我按“Enter”,现在焦点转到第二行(尽管我有4列)。而且,在到达最后一个单元格(最后一行,最后一列)之后,它会给出“索引超出范围”的错误。 - Sukanya
1
是的,我知道那个问题。当时我比较匆忙,所以没有完成它。你可以在到达最后一行时编写代码,如果需要创建新行,则可以创建。 - Kishore Kumar
我在第一天就接受了你的答案..你们两个提供的方案都帮助我解决了问题..所以第二天我也接受了Amrit的答案..我不能接受多于一个答案吗? - Sukanya

11
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
{
    int icolumn = dataGridView1.CurrentCell.ColumnIndex;
    int irow = dataGridView1.CurrentCell.RowIndex;

    if (keyData == Keys.Enter)
    {                                
        if (icolumn == dataGridView1.Columns.Count - 1)
        {
            dataGridView1.Rows.Add();
            dataGridView1.CurrentCell = dataGridView1[0, irow + 1];
        }
        else
        {
            dataGridView1.CurrentCell = dataGridView1[icolumn + 1, irow];
        }
        return true;
    }
    else
        return base.ProcessCmdKey(ref msg, keyData);
    }
}

当UI界面上有一个文本框时,它也会在你按下文本框上的回车键时执行,该文本框位于datagridview旁边。 - qakmak

6

您可以在表单中使用DataGridView的selectionchanged事件。

       private DataGridViewCell _celWasEndEdit;

        private void datagridview_SelectionChanged(object sender, EventArgs e)
    {

        if (MouseButtons != 0) return;

        if (_celWasEndEdit != null && datagridview.CurrentCell != null)
        {
            // if we are currently in the next line of last edit cell
            if (datagridview.CurrentCell.RowIndex == _celWasEndEdit.RowIndex + 1 &&
                datagridview.CurrentCell.ColumnIndex == _celWasEndEdit.ColumnIndex)
            {
                int iColNew;
                int iRowNew = 0;
                if (_celWasEndEdit.ColumnIndex >= datagridview.ColumnCount - 1)
                {
                    iColNew = 0;
                    iRowNew = dgvItems.CurrentCell.RowIndex;                   
                }
                else
                {
                        iColNew = _celWasEndEdit.ColumnIndex + 1;
                        iRowNew = _celWasEndEdit.RowIndex;
                }
                datagridview.CurrentCell = datagridview[iColNew, iRowNew];
            }
        }
        _celWasEndEdit = null;
      }

    private void datagridview_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        _celWasEndEdit = dgvItems[e.ColumnIndex, e.RowIndex];
    }

它只是一个变量,用于跟踪正在被编辑的单元格。 - Amritpal Singh
私有的DataGridViewCell _celWasEndEdit; 我已经在上述解决方案中编写了。 - Amritpal Singh
我想在不编辑的情况下将焦点从一个单元格水平移动到下一个单元格。我该怎么做? - Sukanya
我已经使用过这个很多次了,无论如何我都会重新检查一下我们能做什么。 - Amritpal Singh
1
"MouseButtons",不错的关键字。 - Mystic Lin

2
bool notlastColumn =true; //class level variable--- to check either last column is reached or not

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (dataGridView1.ColumnCount - 1 == e.ColumnIndex)  //if last column
    {
        KeyEventArgs forKeyDown = new KeyEventArgs(Keys.Enter);
        notlastColumn = false;
        dataGridView1_KeyDown(dataGridView1, forKeyDown);
    }
    else
    {
        SendKeys.Send("{up}");
        SendKeys.Send("{right}");
    }
}

private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Enter && notlastColumn) //if not last column move to nex
    {
        SendKeys.Send("{up}");
        SendKeys.Send("{right}");
    }
    else if (e.KeyCode == Keys.Enter)
    {
        SendKeys.Send("{home}");//go to first column
        notlastColumn = true;
    }
}

0
尽管我尝试的代码将焦点移动到下一个单元格,但当单元格处于编辑模式时,它们会影响鼠标点击。最终我想出了以下解决方案。
    bool _dgv_list_cellEndEdit = false; // class level variable

    void dataGridView1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyData == Keys.Enter)
        {
            e.SuppressKeyPress=true;
            SendKeys.Send("{Tab}");
        }
    }

    void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
    {
        _dgv_list_cellEndEdit=true;
    }

    void dataGridView1_MouseDown(object sender, MouseEventArgs e)
    {
        _dgv_list_cellEndEdit=false;
    }

    void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        if(_dgv_list_cellEndEdit)
        {
            _dgv_list_cellEndEdit=false;
            SendKeys.Send("{Up}");
            SendKeys.Send("{Tab}");
        }
    }

0
发布一些修改过的@Amritpal Singhs' answer版本。
如果你的网格的最后一列是hidden(Visible=false)列,那么@Amritpal Singhs的解决方案会抛出错误。下面的解决方案考虑了这些隐藏的列,并且可以正常工作:
private void gridDetails_SelectionChanged(object sender, EventArgs e)
{
   if (MouseButtons != 0) return;

   if (_lastCellEndEdit != null && gridDetails.CurrentCell != null)
   {
       // if we are currently in the next line of last edit cell
       if (gridDetails.CurrentCell.RowIndex == _lastCellEndEdit.RowIndex + 1 &&
           gridDetails.CurrentCell.ColumnIndex == _lastCellEndEdit.ColumnIndex)
       {
           int iColNew;
           int iRowNew = 0;

           var lastCellEndEditColumn = gridDetails.Columns[_lastCellEndEdit.ColumnIndex];
           if (lastCellEndEditColumn.DisplayIndex >= GetVisibleColumnsMaxDisplayIndex())
           {
               iColNew = GetFirstVisibleColumnIndex();
               iRowNew = gridDetails.CurrentCell.RowIndex;
           }
           else
           {
               iColNew = GetNextVisibleColumnIndex(lastCellEndEditColumn.DisplayIndex);
               iRowNew = _lastCellEndEdit.RowIndex;
           }
           gridDetails.CurrentCell = gridDetails[iColNew, iRowNew];
       }
   }
   _lastCellEndEdit = null;

}

private DataGridViewCell _lastCellEndEdit;

private void gridDetails_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
   _lastCellEndEdit = gridDetails[e.ColumnIndex, e.RowIndex];
}

int GetVisibleColumnsMaxDisplayIndex()
{
   int maxDisplayIndex = -1;
   foreach (DataGridViewColumn column in gridDetails.Columns)
   {
       if (column.Visible && column.DisplayIndex > maxDisplayIndex)
       {
           maxDisplayIndex = column.DisplayIndex ;
       }
   }
   return maxDisplayIndex;
}

int GetFirstVisibleColumnIndex()
{
   var firstVisibleColumnDisplayIndex = gridDetails.Columns.Count - 1;
   var firstVisibleColumnIndex = 0;
   foreach (DataGridViewColumn column in gridDetails.Columns)
   {
       if (column.Visible && column.DisplayIndex < firstVisibleColumnDisplayIndex)
       {
           firstVisibleColumnDisplayIndex = column.DisplayIndex;
           firstVisibleColumnIndex = column.Index;
       }
   }
   return firstVisibleColumnIndex;
}

int GetNextVisibleColumnIndex(int previousColumnDisplayIndex)
{
   var nextVisibleColumnDisplayIndex = gridDetails.Columns.Count;
   var nextVisibleColumnIndex = previousColumnDisplayIndex;

   foreach (DataGridViewColumn column in gridDetails.Columns)
   {
       if (column.Visible && column.DisplayIndex > previousColumnDisplayIndex 
           && (column.DisplayIndex - previousColumnDisplayIndex) <= (nextVisibleColumnDisplayIndex - previousColumnDisplayIndex))
       {
           nextVisibleColumnDisplayIndex = column.DisplayIndex;
           nextVisibleColumnIndex = column.Index;
       }
   }
   return nextVisibleColumnIndex;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接