如何通过在 Datagridview 中按下 TAB 上的代码 select winforms 中的下一个控件

How to select next control in winforms from code on TAB pressed inside a Datagridview

我有一个奇怪的问题。在 Winforms 应用程序中,我有一个数据网格视图,我在其中实现了一些代码,用于使用箭头键在其中移动并输入键...

class CalibDataGridView : System.Windows.Forms.DataGridView
    {
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            int row = 0;
            int col = 0;
            // return base.ProcessCmdKey(ref msg, keyData);
            switch (keyData)
            {
                case Keys.Down:
                    return true;
                case Keys.Up:
                    return true;

                case Keys.Right:
                    row = this.CurrentCell.RowIndex;
                    col = this.CurrentCell.ColumnIndex;

                    while (true)
                    {
                        col++;
                        if (col == this.Columns.Count)
                        {
                            row++;
                            col = 0;
                        }

                        if (row == this.Rows.Count)
                        {
                            col = 0;
                            row = 0;
                        }

                        if (!this[col, row].ReadOnly && this[col, row].Visible) break;
                    }

                    this.CurrentCell = this[col, row];

                    return true;

                case Keys.Left:
                    row = this.CurrentCell.RowIndex;
                    col = this.CurrentCell.ColumnIndex;

                    while (true)
                    {
                        col--;
                        if (col < 0)
                        {
                            row--;
                            col = this.Columns.Count - 1;
                        }

                        if (row < 0)
                        {
                            row = this.Rows.Count - 1;
                            col = this.Columns.Count - 1;
                        }

                        if (!this[col, row].ReadOnly && this[col, row].Visible) break;
                    }

                    this.CurrentCell = this[col, row];

                    return true;

                case Keys.Enter:
                    row = this.CurrentCell.RowIndex;
                    col = this.CurrentCell.ColumnIndex;

                    while (true)
                    {

                            row++;
                        if (row == this.Rows.Count)
                        {
                            row = 0;
                        }

                        if (!this[col, row].ReadOnly && this[col, row].Visible) break;
                    }

                    this.CurrentCell = this[col, row];

                    return true;

                default:
                    return base.ProcessCmdKey(ref msg, keyData);
            }
        }
    }

代码工作正常,但我在实现按 TAB 键时移动到下一个控件的功能时遇到问题。我在 datagridview 的 PreviewKeyDown 函数中添加了一些代码:

private void dgvRepeatability1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.PageDown && tbcMain.SelectedIndex > 0)
            {
                tbcMain.SelectedIndex--; //changes tab page
            }
            else if (e.KeyCode == Keys.PageUp && tbcMain.SelectedIndex < 7)
            {

                tbcMain.SelectedIndex++;
            }
            else if (e.KeyCode == Keys.Tab) //does not work like it should!!!!
            {
                Console.Beep(1000, 200);
                this.SelectNextControl((Control)sender, true, true, true, true);

            }
        }

这最后一段代码以奇怪的方式工作...当它在背景中的某个地方被触发时会像它应该的那样改变焦点(它会发出哔哔声并且下一个控件会改变背景颜色所以我可以看到它被聚焦),但是我输了专注于整个表格...我可以按 TAB 键或箭头键或任何其他键,但没有任何反应....

如果我最小化表单然后再次最大化它,焦点将转到下一个控件,就像它首先应该的那样,一切都像它应该的那样工作。

我也试过用 .Select() 和 .Focus() 改变焦点,但没有成功。

在此先感谢您的帮助!

您可以使用 SelectNextControl:

private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    if ( e.KeyCode == Keys.Tab )
    {
        e.Handled = true; 
        this.SelectNextControl((Control)sender, true, true, true, true);
    }

也可以自己找下控件:

private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    if ( e.KeyCode == Keys.Tab )
    {
        e.Handled = true;
        var dataGrid = (DataGridView) sender;
        var tabIndex = dataGrid.TabIndex;
        var controls = this.Controls.Cast<Control>().Where( r => r.TabIndex > tabIndex );
        if ( controls.Any() )
        {
            controls.OrderBy(r => r.TabIndex).First().Select();
        }
        else
        {
            this.Controls.Cast<Control>()
                         .Where( r => r.TabIndex <= tabIndex )
                         .OrderBy( r => tabIndex )
                         .First()
                         .Select();
        }
    }
}