1
votes

The default behavior of DataGrid is to move down when pressing Enter key. I'm trying to change that to move to Right.

I have seen this and have tried to implement it as below. It is kinda working and the it is moving one column to the right when pressing Enter key but it is also moving one row down!

For instance when I'm on cell containing 55 and press enter, I end up on cell containing 20.

I have debugged it but doesn't seem to find what the problem is. The value of the cell is correct in cell.Focus(); and I don't know what happens after that causes this. The odd part is it works when I'm on the last row and press enter.

------------------
| Depth |  Width | 
------------------
|  55  |   30    |
------------------
|  45  |   20    |
------------------

private void PreviewKeyDown(object sender, KeyEventArgs e)
{
    var grid = (DataGrid)sender;

    if (e.Key == Key.Enter || e.Key == Key.Return)
    {
        var columnIndex = grid.Columns.IndexOf(MyDataGrid.CurrentColumn);

        var rowIndex = grid.Items.IndexOf(MyDataGrid.CurrentItem);

        // index of the next column
        columnIndex = columnIndex + 1;

        // reset column index if we are at the end of the row
        if (columnIndex > grid.Columns.Count - 1)
        {
            rowIndex = rowIndex + 1;
            columnIndex = 0;

            // return if we have reached the last row
            if (rowIndex > grid.Items.Count - 1)
            {
                return;
            }
        }

        // there should always be a selected cell
        if (grid.SelectedCells.Count != 0)
        {
            SelectCellByIndex(grid, rowIndex, columnIndex);
        }
    }
}

public static void SelectCellByIndex(DataGrid dataGrid, int rowIndex, int columnIndex)
{
    if (!dataGrid.SelectionUnit.Equals(DataGridSelectionUnit.CellOrRowHeader))
        throw new ArgumentException("The SelectionUnit of the DataGrid must be set to Cell.");

    if (rowIndex < 0 || rowIndex > (dataGrid.Items.Count - 1))
        throw new ArgumentException(string.Format("{0} is an invalid row index.", rowIndex));

    if (columnIndex < 0 || columnIndex > (dataGrid.Columns.Count - 1))
        throw new ArgumentException(string.Format("{0} is an invalid column index.", columnIndex));

    dataGrid.SelectedCells.Clear();

    object item = dataGrid.Items[rowIndex]; //=Product X
    DataGridRow row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
    if (row == null)
    {
        dataGrid.ScrollIntoView(item);
        row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
    }
    if (row != null)
    {
        DataGridCell cell = GetCell(dataGrid, row, columnIndex);
        if (cell != null)
        {
            DataGridCellInfo dataGridCellInfo = new DataGridCellInfo(cell);
            dataGrid.SelectedCells.Add(dataGridCellInfo);
            cell.Focus();
        }
    }
}

public static DataGridCell GetCell(DataGrid dataGrid, DataGridRow rowContainer, int column)
{
    if (rowContainer != null)
    {
        DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
        if (presenter == null)
        {
            /* if the row has been virtualized away, call its ApplyTemplate() method
             * to build its visual tree in order for the DataGridCellsPresenter
             * and the DataGridCells to be created */
            rowContainer.ApplyTemplate();
            presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
        }
        if (presenter != null)
        {
            DataGridCell cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
            if (cell == null)
            {
                /* bring the column into view
                 * in case it has been virtualized away */
                dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
                cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
            }
            return cell;
        }
    }
    return null;
}

public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is T)
            return (T)child;
        else
        {
            T childOfChild = FindVisualChild<T>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}
1

1 Answers

1
votes

The reason is probably because once you're done, the event keeps going through the normal process, and somewhere there it goes done.

What you want to do is at the end of your method, after you've handled it, set the handled to true

 // do your stuff
 e.Handled = true;
 // return here, and it should not go down as well