问题
If I press and hold down either the UP or DOWN arrow key when focused on a DataGridView, the cursor (blue highlighted cell) doesn't move evenly down the rows, instead it jumps several rows at a time in batches. Sometimes it doesn't even seem to move at all until the key is finally released, then the cursor jumps directly to several rows ahead having presumably stored all the key presses.
Here is a GIF image showing the behaviour when pressing and holding the DOWN arrow, then releasing it and pressing and holding the UP arrow.
This movement looks wrong and makes it hard for the user to judge when to release the key to navigate smoothly over several rows. It doesn't even seem to move an number of rows on each jump it makes (like 10-20 rows on each jump, sometimes the whole page, or even reappearing many rows beyond when the user finally releases the key).
For example if the user wants to move the cursor about half way down the page, by pressing the DOWN arrow key and holding it down, then it is very hard to know when to release the key because the cursor is not moving down in an even progress.
Why doesn't it visibly move to each row one at a time in a smooth repeating manner, instead of doing ugly hopping over batches of rows?
This can be reproduced as follows:
- Make a new forms project.
- Drop a DataGridView control onto the form.
- Add a DataGridViewTextBoxColumn in the designer.
Add some rows to the DataGridView, and add a little formatting to make enough rows visible for your test, in the FormLoad event:
private void Form1_Load(object sender, EventArgs e) { dataGridView1.RowTemplate.Height = 14; dataGridView1.Rows.Add(50); dataGridView1.Dock = DockStyle.Fill; }
Then run the program and press and hold the DOWN arrow key to see how the blue highlight jumps down strangely instead of moving smoothly down from row to row.
The strange behaviour exists even when the DataGridView is read only.
I have tried making the grid and the form DoubleBuffered but no success. I have also tried setting the grid to Virtual mode and ReadOnly and changing just about every setting of the grid, but nothing works.
The only way I have discovered to make the cursor to move smoothly and rapidly up or down the rows without jumping over batches of rows, has been to not let the DataGridView be focused. To do this I make another control on the form (for example a textbox, and give focus to the text Box). Then I override the processCmdKey method on the form to capture the keyboard input and if it detects an arrow key then I programmatically change the current cell in the DataGridView (for example to the next row if the DOWN key was detected in processCmdKey). This moves the current cell without ever giving actual focus to the DataGridView. The movement of the highlight then appears to progress evenly and doesn't jump down in strange batches.
- Add a text box onto the form
Add this code to the form:
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); }
Then run the program to test again as follows:
- Click on the text box to give it focus (instead of the grid). Then press and hold the DOWN key, to see that the blue highlighted current cell progresses smoothly down through the rows. Release the key.
- Then click on the grid to give it focus, then press and hold the UP or DOWN arrow key and witness the blue highlight jumping across several rows instead of progressing smoothly.
So the problem exists whenever the DataGridView has focus, regardless of whether the grid handles the keys presses or if I handle them in processCmdKey.
I don't want to rely of keeping focus away from the grid, because there are times when a grid needs to have focus. I'd also have to add a lot more code to processCmdKey to handle all the other potential key presses for a grid, such as tab, page up / down, enter etc., which doesn't seem sensible.
The grid will actually be read only in my application, so it is probably only really the ability to move around smoothly that I need to use, but nevertheless having a dummy control that is focussed instead of the grid doesn't seem sensible.
A slightly similar problem was mentioned here (DataGrid not scrolling smoothly), but it is not Windows Forms and the original poster seemed to state that his problem was fixed by getting rid of all event handling and turning on virtualization, but I've tried virtual mode and I am not handling any events of the grid. He also states that he was on a very busy server. So I think this probably merits me adding this as its own separate question.
Any help would be much appreciated. Thanks :)
回答1:
The problem has now been solved by changing the keyboard repeat speed settings on the computer. I went to Control Panel | Ease of Access | Change How Your Keyboard Works | Scroll down and choose 'See also: Keyboard Settings'. This then displays a window called 'Keyboard Properties', where I had to lower the 'Repeat Rate', I moved the slider slightly form Maximum (about a quarter of the way from maximum) and clicked apply.
The when I re-tested the program, it worked normally and the cursor moved smoothly down the grid when I pressed and held the Down arrow key.
So I am guessing that there is something strange about my PC that made it not able to cope well when using the maximum keyboard repeat rate, in the case of a DataGridView.
In an ideal world, I'd be able to use a really fast keyboard repeat rate set to maximum, but I am happy enough to settle for a slower keyboard repeat rate in order to solve my problem using the arrow keys smoothly on a DataGridView.
@Sinatr, thanks again for helping me by testing the code on your PC, just telling me that you couldn't reproduce it and that I probably had a problem with my PC rather than my code, was a big help.
来源:https://stackoverflow.com/questions/48228254/holding-down-arrow-keys-in-datagridview-not-moving-cursor-smoothly