2012-05-01 27 views
12

Quiero tener una cuadrícula de datos personalizada, que puede, se presionaMover el foco a la siguiente celda al presionar la tecla Entrar ¿WPF DataGrid?

  1. Mover a la siguiente celda cuando Introduzca tecla también si está en modo de edición.
  2. Cuando se alcanza la última columna en la fila actual, el foco debe moverse a la primera celda de la fila siguiente.
  3. Al llegar a la celda siguiente, si la celda es editable, debería ser automáticamente editable.
  4. Si la celda contiene un ComboBox no comboboxcolumn, el combobox debería DropDownOpen.

Por favor, ayúdenme en esto. Lo he intentado desde hace unos días creando un Custom DataGrid y escribí un código en

protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e) 

Pero fallé.

Respuesta

5
private void dg_PreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    try 
    { 
     if (e.Key == Key.Enter) 
     { 
      e.Handled = true; 
      var cell = GetCell(dgIssuance, dgIssuance.Items.Count - 1, 2); 
      if (cell != null) 
      { 
       cell.IsSelected = true; 
       cell.Focus(); 
       dg.BeginEdit(); 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox(ex.Message, "Error", MessageType.Error); 
    } 
} 

public static DataGridCell GetCell(DataGrid dg, int row, int column) 
{ 
    var rowContainer = GetRow(dg, row); 

    if (rowContainer != null) 
    { 
     var presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer); 
     if (presenter != null) 
     { 
      // try to get the cell but it may possibly be virtualized 
      var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column); 
      if (cell == null) 
      { 
       // now try to bring into view and retreive the cell 
       dg.ScrollIntoView(rowContainer, dg.Columns[column]); 
       cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column); 
      } 
      return cell; 
     } 
    } 
    return null; 
} 
+0

He hecho algo similar en algunos proyectos, el código es muy similar. Acabo de extender la cuadrícula de datos y encapsulé una gran parte de lo que está haciendo en ella. ¡Así puedo responder que esta/tu respuesta definitivamente funciona genial! +1 –

+15

Sería bueno ver el código que falta: 'GetRow()', 'GetVisualChild ()' y ¿qué es 'dgIssuance'? – bitbonk

+0

¿Por qué está pasando un valor codificado a su función de GetCell? La pregunta era acerca de pasar a la celda ** siguiente ** cuando se presiona la tecla Intro, pero está tratando de obtener una última celda en su columna 2-n cuando ingrese clic. ¿Por qué? – AndreyS

2
public class DataGrid : System.Windows.Controls.DataGrid 
{ 
    private void PressKey(Key key) 
    { 
     KeyEventArgs args = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, key); 
     args.RoutedEvent = Keyboard.KeyDownEvent; 
     InputManager.Current.ProcessInput(args); 
    } 
    protected override void OnCurrentCellChanged(EventArgs e) 
    { 
     if (this.CurrentCell.Column != null)     
      if (this.CurrentCell.Column.DisplayIndex == 2) 
      { 

       if (this.CurrentCell.Item.ToString() == "--End Of List--") 
       { 
        this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down)); 
       } 
      } 
      else if (this.CurrentCell.Column != null && this.CurrentCell.Column.DisplayIndex == this.Columns.Count() - 1) 
      { 
       PressKey(Key.Return); 
       DataGridCell cell = DataGridHelper.GetCell(this.CurrentCell); 
       int index = DataGridHelper.GetRowIndex(cell); 
       DataGridRow dgrow = (DataGridRow)this.ItemContainerGenerator.ContainerFromItem(this.Items[index]); 
       dgrow.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); 
      } 
    } 
    protected override void OnKeyDown(KeyEventArgs e) 
    { 
     if (e.Key == Key.Enter) 
     { 
      DataGridRow rowContainer = (DataGridRow)this.ItemContainerGenerator.ContainerFromItem(this.CurrentItem); 
      if (rowContainer != null) 
      { 
       int columnIndex = this.Columns.IndexOf(this.CurrentColumn); 
       DataGridCellsPresenter presenter = UIHelper.GetVisualChild<DataGridCellsPresenter>(rowContainer); 
       if (columnIndex == 0) 
       { 
        DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); 
        TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next); 
        request.Wrapped = true; 
        cell.MoveFocus(request); 
        BeginEdit(); 
        PressKey(Key.Down); 
       } 
       else 
       { 
        CommitEdit(); 
        DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); 
        TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next); 
        request.Wrapped = true; 
        cell.MoveFocus(request); 
       } 
       this.SelectedItem = this.CurrentItem; 
       e.Handled = true; 
       this.UpdateLayout(); 
      } 
     } 
    } 
} 

Por el momento, he escrito esto y su trabajo para mí.

+0

Aparece el error 'Error No se encontró el tipo' my: DataGridComboBoxColumn '. Verifique que no le falta una referencia de ensamblado y que todos los ensamblados a los que se hace referencia han sido construidos. ' cuando extiendo datagrid class wats mal – Mussammil

7

Una implementación mucho más simple. La idea es capturar el evento de keydown y si la tecla es "Enter", luego pasar a la siguiente pestaña que es la siguiente celda de la grilla.

/// <summary> 
/// On Enter Key, it tabs to into next cell. 
/// </summary> 
/// <param name="sender"></param> 
/// <param name="e"></param> 
private void DataGrid_OnPreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    var uiElement = e.OriginalSource as UIElement; 
    if (e.Key == Key.Enter && uiElement != null) 
    { 
     e.Handled = true; 
     uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); 
    } 
} 
Cuestiones relacionadas