Search code examples
c#datagridviewkeyevent

Jump n Rows Up or Down in DataGridView on KeyDown or PreviewKeyDown Events


I have trouble implementing arrow key navigation of a DataGridView (no datasource used). The DataGridView has 2 different type of items, most of the time every second item is of the first type, vice versa the others are of the second type. Now if someone presses KeyUp / Down I want the DataGridView to jump to a row of a given index, not one up or down.

No matter how I try to solve this it is not clear when the event actually ends. If I try this inside the _previewKeyDown method:

if (DgvCarPosAndTrafficMsg.CurrentRow != null)
        {
            if (e.KeyCode == Keys.Down)
            {
                if (DgvCarPosAndTrafficMsg.SortOrder == SortOrder.Ascending)
                {
                    for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i < SessionItems.Count; i++)
                    {
                        if (SessionItems[i] is CarPosItem)
                        {
                            DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
                            break;
                        }
                    }
                }
                else
                {
                    for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i > 0; i--)
                    {
                        if (SessionItems[i] is CarPosItem)
                        {
                            DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
                            break;
                        }
                    }
                }
            }
            else if (e.KeyCode == Keys.Up)
            {

                if (DgvCarPosAndTrafficMsg.SortOrder == SortOrder.Descending)
                {
                    for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i < SessionItems.Count; i++)
                    {
                        if (SessionItems[i] is CarPosItem)
                        {
                            DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
                            break;
                        }
                    }
                }
                else
                {
                    for (int i = DgvCarPosAndTrafficMsg.CurrentRow.Index; i > 0; i--)
                    {
                        if (SessionItems[i] is CarPosItem)
                        {
                            DgvCarPosAndTrafficMsg.Rows[i].Selected = true;
                            break;
                        }
                    }
                }
            }

it would still just jump up or down 1 Row. I have no clue when this event is actually processed automatically and I would like to have my own behaviour of key up down events. Please help me, DataGridViews in C# and their annoying events are very hard for me to track down. It seems as every event of those grids is processed differently, for some events the new state has already been applied, for others (OnSelectionChanged) it gets processed afterwards. It is documented poorly and not intuitive, I want to avoid / override all of this background stuff.


Solution

  • Ok I found a solution, using only one event method:

    Here is my code, it is important to set the evenArgs as handled, and then do your own update method of the grid:

        private void DgvCarPosAndTrafficMsg_KeyDown(object sender, KeyEventArgs e)
        {
            int diffDown;
            int diffUp;
            if (DgvCarPosAndTrafficMsg.SortOrder == SortOrder.Descending)
            {
    
                diffDown = 1;
                diffUp = -2;
            }
            else
            {
    
                diffDown = 2;
                diffUp = -1;
            }
    
            if (DgvCarPosAndTrafficMsg.CurrentRow != null)
            {
                if (e.KeyCode == Keys.Down && DgvCarPosAndTrafficMsg.CurrentRow.Index < DgvCarPosAndTrafficMsg.Rows.Count - diffDown)
                {
    
                    DgvCarPosAndTrafficMsg.CurrentCell = DgvCarPosAndTrafficMsg.Rows[DgvCarPosAndTrafficMsg.CurrentRow.Index + diffDown].Cells[0];
                }
                else if (e.KeyCode == Keys.Up && DgvCarPosAndTrafficMsg.CurrentRow.Index + diffUp > 0)
                {
    
                    DgvCarPosAndTrafficMsg.CurrentCell = DgvCarPosAndTrafficMsg.Rows[DgvCarPosAndTrafficMsg.CurrentRow.Index + diffUp].Cells[0];
                }
    
            }
            e.Handled = true;
            DgvCarPosAndTrafficMsg_UpdateAll();
        }
    

    I always jump up/down 2 rows as I expect the item of same type there, but in my UpdateAll() method I check again if it has been correct, and correct it if needed, otherwhise (if already correct) I update the visualisation of the data (and fill other grids with details of the selected entry). I hope this will help others too.

    You might have -2 and + 2 for both events, I have some treatment going on afterwards so these values are my indexes I needed, adjust this according to your case or give a specific index (as seen in the question)