Move Focus to Next Cell on Enter Key Press in WPF

2020-02-04 06:06发布

I want to have a Custom DataGrid which can,

  1. Move to next cell when Enter key is pressed also if it is in edit mode.
  2. When the last column in the current row is reach, the focus should move to the first cell of next row.
  3. On reaching to next cell, if the cell is editable, it should automatically became editable.
  4. If the cell contains an ComboBox not comboboxcolumn, the combobox should DropDownOpen.

Please help me in this. I have been trying from the past few day by creating a Custom DataGrid and wrote some code in

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

But I failed.

5条回答
ら.Afraid
2楼-- · 2020-02-04 06:15

How about this solution? Cancel the action of the Enter key by setting Handled=true and press the Tab key.

public Constructor()
{
  InitializeComponent(); 
  this.SampleDataGrid.PreviewKeyDown += MoveCellOnEnterKey;
}

private void MoveCellOnEnterKey(object sender, KeyEventArgs e)
{
  if(e.Key == Key.Enter)
  {
    // Cancel [Enter] key event.
    e.Handled = true;
    // Press [Tab] key programatically.
    var tabKeyEvent = new KeyEventArgs(
      e.KeyboardDevice, e.InputSource, e.Timestamp, Key.Tab);
    tabKeyEvent.RoutedEvent = Keyboard.KeyDownEvent;
    InputManager.Current.ProcessInput(tabKeyEvent);
  }
}
查看更多
贪生不怕死
3楼-- · 2020-02-04 06:20
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();
            }
        }
    }
}

For the time being, I have written this and its working for me.

查看更多
Bombasti
4楼-- · 2020-02-04 06:31
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;
}
查看更多
相关推荐>>
5楼-- · 2020-02-04 06:34

A much simpler implementation. The idea is to capture the keydown event and if the key is "Enter", then move to the next tab which is next cell of the grid.

/// <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));
    }
}
查看更多
再贱就再见
6楼-- · 2020-02-04 06:34
    Public Sub SendKey(ByVal key As Key)
     Dim args As New KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, key)
        args.RoutedEvent = Keyboard.KeyDownEvent
        InputManager.Current.ProcessInput(args)
    End Sub
Private Sub dataGrid_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles dataGrid.PreviewKeyDown
        Dim i As UIElement = e.OriginalSource
        Dim DG As DataGrid = sender
        If (e.Key = Key.Enter Or e.Key = Key.Return) AndAlso i IsNot Nothing Then
            MyBase.OnKeyDown(e)
            DG.CommitEdit()
            SendKey(Key.Tab)
            e.Handled = True
        End If
    End Sub
查看更多
登录 后发表回答