WPF数据网格和Tab键

时间:2011-04-13 20:17:39

标签: c# wpf datagrid key-bindings

另一个datagrid键绑定问题

我有一个数据网格。它的选择模式设置为FullRow和KeyboardNavigation.TabNavigation =“Once”,我希望得到我想要的结果,但事实并非如此。

当数据网格具有焦点时按下Tab键,它将逐个选中网格中的每一列。因此,如果我选中具有4列的网格,我将不得不按Tab键4次以转到下一个tabindex。

我想要的是第一次按下时tab键从数据网格中直接标签,并将焦点放在下一个tabindex ...如果这是有意义的。

我试过覆盖keydown事件处理程序中的tab键,如此。

class BetterDataGrid : DataGrid
{
  ..............
  protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
  {
    ..............
    if (e.Key == Key.Tab)
    {
        Console.WriteLine("TAB");
        MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }
    .........
  }

它确实将“TAB”写入控制台,但该选项卡仍然保持默认行为。不确定这是否是下一个tabindex的正确方法,但是这应该使tab键除了写入控制台或引起异常外什么都不做。
让我觉得不可能覆盖tab键行为。

希望得到一些有用的意见 一如既往,提前谢谢。

2 个答案:

答案 0 :(得分:9)

我想要这个用于我的业务线软件,我发现解决它的唯一方法是使用datagrid的PreviewKeyDown,GotKeyboardFocus和LostKeyboardFocus事件进行代码隐藏。我已将这些事件处理程序放在WPF装饰器中,以避免为每个DataGrid重复它。可能有可能将DataGrid子类化,但我还没有尝试过。

处理程序的代码如下(DataGrid是x:Name =" grid"对于此示例代码):

        private IInputElement lastDataGridFocus = null;
    private int selectedcolumnindex = 0;

    void grid_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (grid.Items.Count > 0 && (e.NewFocus is DataGrid || (e.NewFocus is DataGridCell && !(e.OldFocus is DataGridCell))))
        {
            DataGridCell cell = null;

            if (lastDataGridFocus != null)
            {
                FocusManager.SetFocusedElement(grid, lastDataGridFocus);
                lastDataGridFocus = null;
                e.Handled = true;
                return;
            }

            if (grid.SelectedCells.Count == 0)
            {
                DataGridRow rowContainer = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(0);
                if (rowContainer != null)
                {
                    DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
                    cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex((selectedcolumnindex < 0) ? 0 : selectedcolumnindex);
                }
            }
            else
            {
                DataGridCellInfo selectedDataGridCellInfo = (grid.SelectedCells[0] as DataGridCellInfo?).Value;
                DataGridRow rowContainer = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(selectedDataGridCellInfo.Item);
                if (rowContainer != null)
                {
                    DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
                    cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex((selectedcolumnindex < 0) ? 0 : selectedcolumnindex);
                }
            }
            if (null != cell)
            {
                FocusManager.SetFocusedElement(grid, cell as IInputElement);
                e.Handled = true;
            }
        }
    }

    void grid_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!(e.NewFocus is DataGridCell))
        {
            if (grid.CurrentCell != null)
            {
                selectedcolumnindex = grid.Columns.IndexOf(grid.CurrentCell.Column);
            }
        }
    }

    void grid_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (Keyboard.Modifiers == ModifierKeys.Shift && e.Key == Key.Tab)
        {
            lastDataGridFocus = Keyboard.FocusedElement;
            grid.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));
            e.Handled = true;
        }
        else if (Keyboard.Modifiers == ModifierKeys.None && e.Key == Key.Tab)
        {
            lastDataGridFocus = Keyboard.FocusedElement;
            grid.MoveFocus(new TraversalRequest(FocusNavigationDirection.Last));
            (Keyboard.FocusedElement as FrameworkElement).MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
            e.Handled = true;
        }
    }

使用此代码,您可以使用光标键在网格内导航,并使用Tab键和shift-tab键将您从数据网格中移出。如果您退出网格并返回网格,您也会进入您离开的同一个单元格。这是我的用户和我想要的,这是IMHO DataGrid控件应该提供的默认行为。

答案 1 :(得分:-2)

你想要实现的不是正确的行为,当DataGrid聚焦时,每个人都希望在按Tab键时像Excel一样导航。如果您不希望用户在DataGrid中导航,最好通过在DataGrid上设置IsTabStop="False"来阻止DataGrid上的制表位。