2011-04-13 104 views
10

另一个datagrid键绑定问题WPF datagrid和tab键

我有一个数据网格。它有选择模式设置为FullRow和KeyboardNavigation.TabNavigation =“一次”,我希望能得到我想要的结果,但它没有。

当数据网格具有焦点时按Tab键时,它将一个一个地在网格中的每个列上进行选择。因此,如果我在具有4列的网格中进行选择,我将不得不按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键不会做任何事情,而是写入控制台或导致异常。
使我认为覆盖标签键行为是不可能的。

希望得到一些有用的意见。
一如既往,在此先感谢。

回答

9

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

的处理程序的代码如下(数据网格为x:名称=“网格”对于本示例代码):

 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键让你走出数据网格。如果您退出网格并返回网格,您也会到达您离开的同一个单元格。这是我的用户和我想要的,这是恕我直言,DataGrid控件应该提供什么作为默认行为。

+1

抱歉,迟到的接受,没有得到测试的机会,但这是好的。谢谢 – 2011-05-18 00:14:27

-2

你试图达到的目标不是正确的行为,每个人都希望当DataGrid专注时按下Tab键的时候Excel就像导航一样。如果您不希望用户浏览DataGrid,最好通过在DataGrid上设置IsTabStop="False"来防止DataGrid上的制表位停止。

+3

为什么选择倒票?这只是我从UX角度看的意见! – 2011-04-13 21:11:39

+1

是的,我同意你Fadil先生,最好是设置IsTabStop =“False” – 2011-04-13 21:15:24

+2

对不起,但你的回答并没有真正的帮助。 IsTabStop = false会将选项卡带入网格中,我希望保留网格,并且在重点关注时不会产生所需的行为。很多情况下,Excel风格的导航运行良好,但在这种情况下,它只是多余的,网格是只读的,并且具有全行选择。 – 2011-04-13 21:33:54