Reputation: 37633
Sometimes keys up down are not working on DataGridView
.
I have no clue why and especially it is weird because there is no code assigned to key's events of DataGridView
...
SelectionMode is FullRowSelect
Multiselect is False
This code dos not help...
private void dataGridView1_PreviewKeyDown(object sender, reviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Down:
e.IsInputKey = true;
break;
case Keys.Up:
e.IsInputKey = true;
break;
}
}
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Down)
{
e.Handled = true;
}
else if (e.KeyData == Keys.Up)
{
e.Handled = true;
}
}
Any clue?
P.S.
It seems like the SelectionChanged
method does some hard work... So When I disable it eberything is fine.
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
// Some hard work
}
So the quesion is how to optimize it.
I assume to use Timer so when user stops select arrows keys 1 second later
code of the SelectionChanged
method should be executed.
Any clue about the best way to do it?
Upvotes: 4
Views: 765
Reputation: 1
Maybe its to late but in my problem, using e.Handled = true
is the problem.
Put wisely where the command should placed for.
Example :
If on event Key Down, and every Key Enter that user press you want the selected row dont move down and you use the event e.Handled
. Put that command like this :
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
//Do the command
}
Dont use outside the if condition because it will freeze the selected row no matther what key that user press.
In your case, using e.Handled
inside Up and down Key Press event just makes it worst, cause every time user press the key, the selected row wont move Up or Down cause with the command e.Handled
, you command the program to not move the cursor from the selected row.
Sorry for my bad english...
Upvotes: 0
Reputation: 19
Notice that when you PopulateTabs()
you then have to set the Focus back to the DataGridView
again. This was your problem with the Up and Down arrow keys. The events for the keys were being caught by your custom control(s). As for the very hard work (PopulateTabs), I notice you're using asynchronous threading with the TPL
. Have you thought of doing away with the sleep interval as it seems redundant just set your DoesHardWork variable and change the focus to the DataGridView
outside the Task. The reason it is working the way it does at the moment is that the SelectionChanged
event fires twice the first time it "DoesHardWork" the second time it falls through as DoesHardWork is still false while it is processing the PopulateTabs()
. A more elegant solution would be to set the CellValue/RowValue/Control which is generated by PopulateTabs()
to the Object you would return from PopulateTabs() using IAsyncResult
.
Something Like This :
bool canDoHardWork = true;
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (canDoHardWork)
{
IAsyncResult result;
Task.Factory.StartNew(() =>
{
canDoHardWork = false;
result = this.BeginInvoke((Func<Button>)(() =>
{
canDoHardWork = true;
return PopulateTabs(); // Very hard work
}), null);
this.dataGridView1.Controls.Add((Button)this.EndInvoke(result));
dataGridView1.Focus();
});
}
}
There's no need to wait for the thread to complete as when it does it will just add the custom control to the DataGridView and return the control to the main thread. The thread sleep in your example would occur on the asynchronous thread and is as such redundant. In this example the heavy lifting is performed on another thread leaving the main thread free to continue accepting input. Have to put the focus for the DataGridView after the addition of the control or the focus won't change when it needs to.
Upvotes: 1
Reputation: 37633
Somehow during of executing SelectionChanged
the grid losts its focus.
And probably it is happening because of the creation and inserting User Controls on fly.
So I did three adjustments and now it is fine!
bool canDoHardWork = true;
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (canDoHardWork)
{
int interval = 2000; // Just 2 seconds
Task.Factory.StartNew(() =>
{
canDoHardWork= false;
Thread.Sleep(interval);
this.BeginInvoke((Action)(() =>
{
PopulateTabs(); // Very hard work
dataGridView1.Focus();
canDoHardWork= true;
}), null);
});
}
}
Upvotes: 1