I want to move cells with keyboard arrow keys while editing WPF datagrid.

JunYoungLee 161 Reputation points
2022-06-16T15:43:46.023+00:00

I have created a datagrid in WPF. But I want to move with keyboard arrow left, right keys, but there is a problem.
For example I want to move right by pressing the right arrow key while editing a cell in row 1 column 1.
However, while the cell is being edited, the cell does not move in either direction. Is there a way to make the cell move in that direction when the keyboard arrow key is pressed while editing?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,670 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,234 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
762 questions
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 47,966 Reputation points
    2022-06-16T16:34:23.323+00:00

    That's because when you're in edit mode the editing control is getting the keyboard input, not the grid. You need to move it out of edit mode.

    Off the top of my head I'd say do the following. Handle the keyboard KeyUp event. When the desired key(s) are pressed then check to see if the cell is currently being edited using the IsEditing property. Depending upon your desired behavior either CancelEdit or CommitEdit to exit edit mode. Then give the corresponding cell focus.

    This is predicated on the grid actually getting the keyboard event though. It is possible the edit control being used doesn't let it tunnel up. You also might need to handle the boundary cases like the user being on the first/last row/column, the cell being out of view, etc.


1 additional answer

Sort by: Most helpful
  1. JunYoungLee 161 Reputation points
    2022-06-18T03:32:27.107+00:00

    Thank you cooldadtx.
    Referring to your answer, I added a keyup handler to the datagrid to create a code that saves the text being edited and moves the cell when the arrow key is pressed while editing.
    This may not be the best workaround, but it still works. I attached my code below.

            private void datagrid_eqp_KeyUp(object sender, KeyEventArgs e)  
            {  
                //key event  
                DataGrid dg = sender as DataGrid;  
                DataGridCellInfo cellinfo = dg.CurrentCell;  
                DataGridCell cell = TryToFindGridCell(dg, cellinfo);  
                var columnIndex = dg.Columns.IndexOf(dg.CurrentColumn);  
                var rowIndex = dg.Items.IndexOf(dg.CurrentItem);  
      
                if (cell.IsEditing == true && e.Key == Key.Right)  
                {                       
                    //cancel edit, save current text, move cell  
                    cell.Content = "dummy";         //when press arrow, "dummy" deleted and current text is saved  
                    this.datagrid_eqp.CancelEdit();  
                    try  
                    {  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex], datagrid_eqp.Columns[columnIndex + 1]);  
                    }  
                    catch (System.ArgumentOutOfRangeException)  
                    {  
                        //last column exception  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex], datagrid_eqp.Columns[columnIndex]);  
                    }  
                }  
                else if (cell.IsEditing == true && e.Key == Key.Left)  
                {  
                    //cancel edit, save current text, move cell  
                    cell.Content = "dummy";  
                    this.datagrid_eqp.CancelEdit();  
                    try  
                    {  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex], datagrid_eqp.Columns[columnIndex - 1]);  
                    }  
                    catch (System.ArgumentOutOfRangeException)  
                    {  
                        //first column exception  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex], datagrid_eqp.Columns[columnIndex]);  
                    }  
                }  
                else if (cell.IsEditing == true && e.Key == Key.Up)  
                {  
                    //cancel edit, save current text, move cell  
                    cell.Content = "dummy";  
                    this.datagrid_eqp.CancelEdit();  
                    try  
                    {  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex - 1], datagrid_eqp.Columns[columnIndex]);  
                    }  
                    catch (System.ArgumentOutOfRangeException)  
                    {  
                        //first row exception  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex], datagrid_eqp.Columns[columnIndex]);  
                    }  
                }  
                else if (cell.IsEditing == true && e.Key == Key.Down)  
                {  
                    //cancel edit, save current text, move cell  
                    cell.Content = "dummy";  
                    this.datagrid_eqp.CancelEdit();  
                    try  
                    {  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex + 1], datagrid_eqp.Columns[columnIndex]);  
                    }  
                    catch (System.ArgumentOutOfRangeException)  
                    {  
                        //last row exception  
                        this.datagrid_eqp.CurrentCell = new DataGridCellInfo(datagrid_eqp.Items[rowIndex], datagrid_eqp.Columns[columnIndex]);  
                    }  
                }  
      
            }  
     
            static DataGridCell TryToFindGridCell(DataGrid grid, DataGridCellInfo cellInfo)  
            {  
                DataGridCell result = null;  
                DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(cellInfo.Item);  
                if (row != null)  
                {  
                    int columnIndex = grid.Columns.IndexOf(cellInfo.Column);  
                    if (columnIndex > -1)  
                    {  
                        DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);  
                        result = presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell;  
                    }  
                }  
                return result;  
            }  
      
            static T GetVisualChild<T>(Visual parent) where T : Visual  
            {  
                T child = default(T);  
                int numVisuals = VisualTreeHelper.GetChildrenCount(parent);  
                for (int i = 0; i < numVisuals; i++)  
                {  
                    Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);  
                    child = v as T;  
                    if (child == null)  
                    {  
                        child = GetVisualChild<T>(v);  
                    }  
                    if (child != null)  
                    {  
                        break;  
                    }  
                }  
                return child;  
            }  
        }