在数据网格视图中按住箭头键无法平滑移动光标



如果我在专注于 DataGridView 时按住向上或向下箭头键,光标(蓝色突出显示的单元格)不会均匀地向下移动行,而是一次批量跳转几行。 有时它甚至似乎根本不移动,直到最终释放键,然后光标直接跳到前面的几行,大概存储了所有的按键。

这是一个 GIF 图像,显示了按住向下箭头时的行为,然后松开它并按住向上箭头时的行为。

此移动看起来是错误的,使用户难以判断何时释放键以在几行上流畅导航。 它甚至似乎不会在每次跳转时移动许多行(例如每次跳转时移动 10-20 行,有时是整个页面,甚至在用户最终释放密钥之后重新出现许多行)。

例如,如果用户想要通过按向下箭头键并按住光标将光标移动到页面下方的一半左右,则很难知道何时释放该键,因为光标没有均匀地向下移动。

为什么它不以平滑的重复方式一次明显地移动到每一行,而不是在成批的行上做丑陋的跳跃?

可以按如下方式复制:

  • 创建一个新的窗体项目。
  • 将 DataGridView 控件拖放到窗体上。
  • 在设计器中添加 DataGridViewTextBoxColumn。
  • 在 FormLoad 事件中向 DataGridView 添加一些行,并添加一些格式以使足够的行对测试可见:

    private void Form1_Load(object sender, EventArgs e)
    {
    dataGridView1.RowTemplate.Height = 14;
    dataGridView1.Rows.Add(50);
    dataGridView1.Dock = DockStyle.Fill;
    }
    

然后运行程序并按住向下箭头键,看看蓝色突出显示如何奇怪地向下跳跃,而不是从一行平稳地向下移动到另一行。

即使 DataGridView 是只读的,这种奇怪的行为也存在。

我尝试制作网格和表格双缓冲,但没有成功。 我还尝试将网格设置为虚拟模式和只读模式,并更改网格的几乎所有设置,但没有任何效果。

我发现使光标在不跳过成批行的情况下平滑快速地上下移动的唯一方法是不让 DataGridView 聚焦。 为此,我在窗体上创建了另一个控件(例如文本框,并将焦点放在文本框上)。 然后,我重写窗体上的 processCmdKey 方法以捕获键盘输入,如果它检测到箭头键,则以编程方式更改 DataGridView 中的当前单元格(例如,如果在 processCmdKey 中检测到 DOWN 键,则更改为下一行)。 这将移动当前单元格,而不会将实际焦点提供给 DataGridView。 然后,高光的移动似乎进展均匀,并且不会以奇怪的批次跳下来。

  • 向窗体添加文本框
  • 将此代码添加到表单中:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
    int currentRowIndex = dataGridView1.CurrentCell.RowIndex;
    switch (keyData)
    {
    case Keys.Up:
    // Check not already at the first row in the grid before moving up one row
    if (currentRowIndex > 0)
    dataGridView1.CurrentCell = dataGridView1.Rows[currentRowIndex - 1].Cells[dataGridView1.CurrentCell.ColumnIndex];
    return true;
    case Keys.Down:
    // Check not already at the last row in the grid before moving down one row
    if (currentRowIndex + 1 < dataGridView1.Rows.Count)
    dataGridView1.CurrentCell = dataGridView1.Rows[currentRowIndex + 1].Cells[dataGridView1.CurrentCell.ColumnIndex];
    return true;
    }
    // Line below is reached if we didn't handle the key in this method, it tells the form/control to handle it
    return base.ProcessCmdKey(ref msg, keyData);
    }
    

然后运行程序再次测试,如下所示:

  • 单击文本框以使其获得焦点(而不是网格)。 然后按住 向下 键,以查看蓝色突出显示的当前单元格在行中平滑地向下移动。 松开密钥。
  • 然后单击网格以使其聚焦,然后按住向上或向下箭头键,见证蓝色突出显示在几行上跳跃而不是平滑进行。

因此,只要 DataGridView 具有焦点,无论网格是否处理按键或我是否在 processCmdKey 中处理它们,问题都存在。

我不想依赖将焦点从网格上移开,因为有时网格需要焦点。 我还必须向 processCmdKey 添加更多代码来处理网格的所有其他潜在按键,例如制表符、向上/向下翻页、输入等,这似乎并不明智。

网格实际上只会在我的应用程序中读取,因此我可能需要使用的功能可能只是流畅移动的能力,但是拥有一个聚焦而不是网格的虚拟控件似乎并不明智。

这里提到了一个稍微类似的问题(DataGrid 无法流畅滚动),但它不是 Windows 窗体,原始海报似乎指出他的问题已通过摆脱所有事件处理和打开虚拟化来解决,但我尝试了虚拟模式,我没有处理网格的任何事件。 他还说他在一个非常繁忙的服务器上。 所以我认为这可能值得我把它作为它自己的单独问题添加。

任何帮助将不胜感激。 谢谢:)

现在,通过更改计算机上的键盘重复速度设置,该问题已得到解决。 我去了控制面板 |轻松访问 |更改键盘的工作方式 |向下滚动并选择"另请参阅:键盘设置"。 然后,这会显示一个名为"键盘属性"的窗口,我必须在其中降低"重复速率",我将滑块从最大值稍微移动(大约是最大值的四分之一),然后单击应用。

当我重新测试该程序时,它工作正常,当我按住向下箭头键时,光标在网格中平滑移动。

所以我猜测我的 PC 有一些奇怪的地方,使得它在使用 DataGridView 的情况下使用最大键盘重复率时无法很好地应对。

在理想情况下,我能够使用设置为最大值的非常快的键盘重复速率,但我很高兴接受较慢的键盘重复速率,以便在 DataGridView 上顺利使用箭头键解决我的问题。

@Sinatr,再次感谢您通过在您的 PC 上测试代码来帮助我,只是告诉我您无法重现它,并且我的 PC 而不是我的代码可能有问题,这是一个很大的帮助。

最新更新