Подтвердить что ты не робот

Переместить фокус в следующую ячейку при нажатии клавиши Нажмите в WPF DataGrid?

Я хочу иметь пользовательский DataGrid, который может,

  • Переход к следующей ячейке при нажатии клавиши Enter также, если она находится в режиме редактирования.
  • Когда последний столбец в текущей строке достигнут, фокус должен перейти в первую ячейку следующей строки.
  • При достижении следующей ячейки, если ячейка редактируема, она должна автоматически стать редактируемой.
  • Если ячейка содержит ComboBox не comboboxcolumn, то combobox должен DropDownOpen.

Пожалуйста, помогите мне в этом. Я пытался с последних дней создать пользовательский DataGrid и написал код в

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

Но я потерпел неудачу.

4b9b3361

Ответ 1

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

Ответ 2

Более простая реализация. Идея состоит в том, чтобы зафиксировать событие keydown, и если ключ "Enter", перейдите к следующей вкладке, следующей ячейке сетки.

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

Ответ 3

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

В настоящее время я написал это и его работу для меня.

Ответ 4

    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

Ответ 5

Как насчет этого решения? Отмените действие клавиши Enter, установив Handled=true и нажмите клавишу Tab.

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

Ответ 6

    private void Datagrid_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            if (Keyboard.FocusedElement is UIElement elementWithFocus)
            {
                switch (dvDataGrid.CurrentCell.Column.DisplayIndex)
                {
                    case 3
                        :
                        DataGridRow
                            CurrentRows =
                                dvDataGrid.ItemContainerGenerator.ContainerFromItem(dvDataGrid.CurrentItem) as
                                    DataGridRow;
                        elementWithFocus.MoveFocus
                            (new TraversalRequest(FocusNavigationDirection.Next));
                        e.Handled = true;
                        break;
                    default:
                        DataGridRow CurrentRowsdea =
                            dvDataGrid.ItemContainerGenerator.ContainerFromItem(dvDataGrid.CurrentItem) as
                                DataGridRow;
                        elementWithFocus.MoveFocus
                            (new TraversalRequest(FocusNavigationDirection.Next));
                        e.Handled = true;
                        break;
                }
            }
        }
    }