DataGridView按住方向键光标跳转异常问题求助
I’ve dealt with this exact frustration before—tiny row heights in WinForms DataGridView completely break the default arrow key navigation. Instead of smooth, one-row-at-a-time movement when holding the keys, you get those jarring batch jumps or delayed reactions. Let’s fix this properly without ditching normal focus behavior.
What’s Causing This?
The issue comes down to how Windows handles repeated key presses paired with DataGridView’s built-in scrolling/selection logic. When you hold an arrow key, the OS sends repeated key-down events, but the control tries to optimize by scrolling/selecting multiple rows at once—this backfires badly with small row heights, leading to the erratic behavior you’re seeing.
The Proper Solution: Custom DataGridView Control
Instead of hacking around with other controls or overriding the form’s key handling, create a custom DataGridView that takes full control of arrow key navigation. This keeps the control focused and ensures smooth, precise movement.
Here’s the code for the custom control:
using System.Windows.Forms; public class SmoothScrollDataGridView : DataGridView { protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { // Target only up/down arrow keys (no modifiers like Ctrl/Shift) var key = keyData & Keys.KeyCode; if (key == Keys.Down || key == Keys.Up) { int currentRow = CurrentCell?.RowIndex ?? 0; int delta = key == Keys.Down ? 1 : -1; int newRow = currentRow + delta; // Keep navigation within valid row bounds if (newRow >= 0 && newRow < RowCount) { // Explicitly set the current cell to the target row CurrentCell = Rows[newRow].Cells[CurrentCell?.ColumnIndex ?? 0]; // Ensure the new row is visible (handles scrolling automatically) FirstDisplayedScrollingRowIndex = newRow; return true; // Mark the key press as handled to skip default logic } } // Let the base control handle all other keys normally return base.ProcessCmdKey(ref msg, keyData); } }
How to Implement This
- Add this class to your WinForms project.
- Rebuild your project—you’ll see
SmoothScrollDataGridViewappear in the toolbox. - Replace your existing DataGridView with this custom control (either via the designer or programmatically).
- Test holding the up/down arrows—you’ll get smooth, one-row-at-a-time movement, even with row heights as small as 14.
Why This Beats Your Temporary Workaround
- No focus hacks: The DataGridView stays focused, so all normal control behavior (like cell selection, editing if enabled) works as expected.
- Minimal code: You don’t have to handle a ton of edge cases for other keys—we only override the problematic arrow key logic.
- Built-in scrolling: The
FirstDisplayedScrollingRowIndexensures the new row stays in view, so scrolling works seamlessly without jumps.
Extra Tips
- This works perfectly with ReadOnly DataGridViews, which matches your scenario.
- If you need smooth column navigation too (left/right arrows), extend the logic to check
Keys.Left/Keys.Rightand adjust the column index instead of the row index. - You can still keep
DoubleBufferedenabled if you need it for rendering performance—it won’t interfere with this solution.
内容的提问来源于stack exchange,提问作者pipalot

