在 WPF DataGrid 中按 Enter 键时移动到下一列

Move to the next column when pressing Enter key in WPF DataGrid

DataGrid 的默认行为是按下 Enter 键时向下移动。我正在尝试将其更改为 Right.

我已经看到 this 并尝试按如下方式实现它。它有点工作,当按下 Enter 键时它向右移动一列,但它也向下移动一行!

例如,当我在包含 55 的单元格上并按回车键时,我最终会在包含 20.

的单元格上

我已经调试过了,但似乎没有找到问题所在。 单元格的值在 cell.Focus(); 中是正确的,我不知道之后会发生什么导致这种情况。 奇怪的是当我在最后一行时它有效然后按回车键。

------------------
| 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;
}

原因可能是因为一旦你完成了,事件就会继续进行正常的流程,并且在某个地方完成。

你想做的是在你的方法结束时,在你处理它之后,将 handled 设置为 true

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