NoWar
NoWar

Reputation: 37633

Sometimes keys up down are not working on DataGridView

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

Answers (3)

Rian Bello
Rian Bello

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

WilliamP
WilliamP

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

NoWar
NoWar

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

Related Questions