2011-04-13 35 views
10

Otra combinación de teclas de tabla de datos preguntaWPF datagrid y la tecla de tabulación

Tengo una cuadrícula de datos. Tiene el modo de selección configurado en FullRow y KeyboardNavigation.TabNavigation = "Once", que esperaba que obtuviera el resultado deseado, pero no es así.

Cuando se presiona la tecla de tabulación cuando la cuadrícula de datos tiene foco, se tabulará una por una sobre cada columna en la grilla. Entonces, si inserto en la cuadrícula que tiene 4 columnas, tendré que presionar la pestaña 4 veces para ir al siguiente tabindex.

Lo que quiero es que la tecla de tabulación salga de la cuadrícula de datos al presionarlo primero y darle enfoque al próximo tabindex ... si tiene sentido.

He intentado sobreescribir la tecla de tabulación en el controlador de eventos keydown como tal.

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

Escribe "TAB" en la consola pero la pestaña aún conserva su comportamiento predeterminado. No estoy seguro de si esta es la manera correcta de pasar al siguiente tabindex, pero esto debería hacer que la tecla de tabulación no haga más que escribir en la consola o causar una excepción.
Me hace pensar que es imposible anular el comportamiento de la tecla de tabulación.

Esperando por una entrada útil.
Como siempre, gracias de antemano.

Respuesta

9

Quería esto para mi software de línea de negocio, y la única forma que he encontrado para resolverlo es por código subyacente, utilizando los eventos PreviewKeyDown, GotKeyboardFocus y LostKeyboardFocus de la cuadrícula de datos. Puse estos manipuladores de eventos en un decorador de WPF, para evitar repetirlo para cada DataGrid. Probablemente sería posible crear una subclase de DataGrid, pero no lo he intentado.

El código para los manipuladores son los siguientes (cuadrícula de datos es x: Name = "red" de este código de ejemplo):

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

Con este código se puede navegar dentro de la cuadrícula utilizando las teclas del cursor, y la tecla tab y la tecla shift-tab lo sacan de la cuadrícula de datos. Si sale de la cuadrícula y regresa a la cuadrícula, también llega a la misma celda que dejó. Esto es lo que mis usuarios y yo queremos, y esto es en mi humilde opinión, lo que el control DataGrid debería proporcionar como comportamiento predeterminado.

+1

Lo siento por la tardía aceptación, no tuve la oportunidad de probarlo, pero esto es bueno. Gracias –

-2

Lo que está tratando de lograr no es el comportamiento correcto, todos esperan que Excel les guste la navegación al presionar la tecla Tab mientras se enfoca DataGrid. Es mejor evitar las tabulaciones en DataGrid configurando IsTabStop="False" en DataGrid si no desea que el usuario navegue a través de DataGrid.

+3

¿Por qué votar? ¡Es solo mi opinión desde el punto de vista de UX! –

+1

Sí, estoy de acuerdo contigo Sr. Fadil, es mejor configurar IsTabStop = "False" –

+2

Disculpe el voto negativo, pero su respuesta realmente no ayudó en absoluto. IsTabStop = false quita la tabulación en la grilla, que me gustaría conservar y no da como resultado el comportamiento deseado cuando está enfocado. Seguro que en muchos casos la navegación al estilo Excel funciona bien, pero en este caso es simplemente redundante, la grilla es solo de lectura y tiene una selección completa. –