如何实现WPF Datagrid箭头键导航如Tab导航

发布于 2024-10-10 12:47:04 字数 291 浏览 6 评论 0原文

我有一个带有几个可编辑单元格的 DataGrid。用户可以通过选项卡浏览每个单元格来编辑内容。现在我想实现右箭头键像 tab 一样工作。因此,当用户完成编辑一个单元格并按右箭头键时,焦点将移动到下一个可编辑单元格并开始编辑。

例如,我有以下屏幕:

当用户按右箭头键时,我希望我的数据网格如下所示:

I have a DataGrid with few editable cells. Users can tab through each cells to edit the content. Now I want to implement the right arrow key working just like tab. So when a user finishes editing one cell and they press right arrow key, the focus moves to the next editable cell and starts editing.

For example, I have follow screen:

When user press right arrow key, I want my datagrid to be like this:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

作死小能手 2024-10-17 12:47:04

DataGrid 实际上自动处理右、左、上、下箭头键。话虽这么说,您可以使用任何这些键移动单元格焦点,然后开始键入以进入编辑模式(前提是单元格可编辑)。您不必监听按键事件。请注意,如果您按“Enter”,那么您将移至下一行。

编辑:

当然,默认情况下箭头键不会将单元格置于编辑模式。相反,您必须输入内容或使用鼠标指针。但是,您可以执行以下操作:

    private void myDataGrid_CurrentCellChanged(object sender, EventArgs e)
    {
        myDataGrid.BeginEdit();
    }

这将强制焦点所在的单元格进入编辑模式。我尝试使用按键事件处理程序,但似乎 DataGrid 不会让用户监听箭头键和 Enter(尽管如果您使用 WIN32 API,则可以)。现在,每当您使用任何箭头键时,新选择的单元格都将处于编辑模式。尝试按 Esc 键退出此模式。

The DataGrid actually auto-handles right, left, up, down arrow keys. That being said, you can move the cell focus around using any of those keys and then start typing to get into the edit mode (iff the cell is editable). You don't have to listen to key press down events. Note that if you hit "Enter", then you will move to the next row.

EDIT:

Of course, by default the arrow keys won't put a cell into edit mode. Instead, you have to type in stuff or use the mouse pointer. But, you can do the following:

    private void myDataGrid_CurrentCellChanged(object sender, EventArgs e)
    {
        myDataGrid.BeginEdit();
    }

This will force the cell on focus to enter the edit mode. I tried using key event handlers, but it seems the DataGrid won't let the user listen to the arrow keys and Enter (although you could if you use WIN32 API). Now, whenever you use any of the arrow keys, the newly selected cell will be in edit mode. Try hitting Esc to escape this mode.

So尛奶瓶 2024-10-17 12:47:04

这是我使用箭头键进行导航的代码

,它放置在 Datagrid_KeyUp 事件内,

    DataGridCell DGcell = new DataGridCell();
    DGcell = GetCell(index, _Header);
    if (DGcell != null)
    {
         CurrentCellContentType = DGcell.Content.GetType().Name.ToString();
    }
    DataGridCell ProdCodeCell = GetCell(index, 0);
    DataGridCell DescCell = GetCell(index, 1);
    DataGridCell CostPriceCell = GetCell(index, 4);
    DataGridCell VatRateCell = GetCell(index, 9);

    DataGridCellInfo PCell = new DataGridCellInfo(ProdCodeCell);
    DataGridCellInfo DCell = new DataGridCellInfo(DescCell);
    DataGridCellInfo PriceCell = new DataGridCellInfo(CostPriceCell);
    DataGridCellInfo VatCell = new DataGridCellInfo(VatRateCell);

    string ProdCellContentType = PCell.Column.GetCellContent(PCell.Item).GetType().Name.ToString();
    string DescCellContentType = DCell.Column.GetCellContent(DCell.Item).GetType().Name.ToString();
    string PriceCellContentType = PriceCell.Column.GetCellContent(PriceCell.Item).GetType().Name.ToString();
    string VatCellContentType = VatCell.Column.GetCellContent(VatCell.Item).GetType().Name.ToString();

    switch (e.Key)
    {
    case Key.Left:
        if (CurrentCellContentType == "TextBlock") e.Handled = false;
        else if (CurrentCellContentType == "TextBox")
        {
            DataGridCellInfo cellLeft = new DataGridCellInfo(GetCell(index, _Header - 1));
            DgInvoiceLines.CurrentCell = cellLeft;
        }
        break;
    case Key.Right:
        if (CurrentCellContentType == "TextBlock") else e.Handled = false;

        else if (CurrentCellContentType == "TextBox")
        {
            DataGridCellInfo cellRight = new DataGridCellInfo(GetCell(index, _Header + 1));
            DgInvoiceLines.CurrentCell = cellRight;
        }
        break;
    case Key.Up:
        if (index != 0)
        {
            if (CurrentCellContentType == "TextBlock") e.Handled = false;
            else if (CurrentCellContentType == "TextBox")
            {
                DataGridCellInfo cellUp = new DataGridCellInfo(GetCell(index - 1, _Header));
                DgInvoiceLines.CurrentCell = cellUp;
                DgInvoiceLines.SelectedItem = DgInvoiceLines.Items[index - 1];
            }
        }
        break;

    case Key.Down:
        if (CurrentCellContentType == "TextBlock") e.Handled = false;
        else if (CurrentCellContentType == "TextBox")
        {
            DataGridCellInfo cellDown = new DataGridCellInfo(GetCell(index + 1, _Header));
            DgInvoiceLines.CurrentCell = cellDown;
            DgInvoiceLines.SelectedItem = DgInvoiceLines.Items[index + 1];
        }
        break;

我使用 switch 语句为每个列标题

HTH 分配一个数字。

This is the code I use for navigation using the arrow keys

Its placed inside the Datagrid_KeyUp event

    DataGridCell DGcell = new DataGridCell();
    DGcell = GetCell(index, _Header);
    if (DGcell != null)
    {
         CurrentCellContentType = DGcell.Content.GetType().Name.ToString();
    }
    DataGridCell ProdCodeCell = GetCell(index, 0);
    DataGridCell DescCell = GetCell(index, 1);
    DataGridCell CostPriceCell = GetCell(index, 4);
    DataGridCell VatRateCell = GetCell(index, 9);

    DataGridCellInfo PCell = new DataGridCellInfo(ProdCodeCell);
    DataGridCellInfo DCell = new DataGridCellInfo(DescCell);
    DataGridCellInfo PriceCell = new DataGridCellInfo(CostPriceCell);
    DataGridCellInfo VatCell = new DataGridCellInfo(VatRateCell);

    string ProdCellContentType = PCell.Column.GetCellContent(PCell.Item).GetType().Name.ToString();
    string DescCellContentType = DCell.Column.GetCellContent(DCell.Item).GetType().Name.ToString();
    string PriceCellContentType = PriceCell.Column.GetCellContent(PriceCell.Item).GetType().Name.ToString();
    string VatCellContentType = VatCell.Column.GetCellContent(VatCell.Item).GetType().Name.ToString();

    switch (e.Key)
    {
    case Key.Left:
        if (CurrentCellContentType == "TextBlock") e.Handled = false;
        else if (CurrentCellContentType == "TextBox")
        {
            DataGridCellInfo cellLeft = new DataGridCellInfo(GetCell(index, _Header - 1));
            DgInvoiceLines.CurrentCell = cellLeft;
        }
        break;
    case Key.Right:
        if (CurrentCellContentType == "TextBlock") else e.Handled = false;

        else if (CurrentCellContentType == "TextBox")
        {
            DataGridCellInfo cellRight = new DataGridCellInfo(GetCell(index, _Header + 1));
            DgInvoiceLines.CurrentCell = cellRight;
        }
        break;
    case Key.Up:
        if (index != 0)
        {
            if (CurrentCellContentType == "TextBlock") e.Handled = false;
            else if (CurrentCellContentType == "TextBox")
            {
                DataGridCellInfo cellUp = new DataGridCellInfo(GetCell(index - 1, _Header));
                DgInvoiceLines.CurrentCell = cellUp;
                DgInvoiceLines.SelectedItem = DgInvoiceLines.Items[index - 1];
            }
        }
        break;

    case Key.Down:
        if (CurrentCellContentType == "TextBlock") e.Handled = false;
        else if (CurrentCellContentType == "TextBox")
        {
            DataGridCellInfo cellDown = new DataGridCellInfo(GetCell(index + 1, _Header));
            DgInvoiceLines.CurrentCell = cellDown;
            DgInvoiceLines.SelectedItem = DgInvoiceLines.Items[index + 1];
        }
        break;

I use a switch statement to assign a number to each column header

HTH.

养猫人 2024-10-17 12:47:04

这是我的解决方案,有效。

在构造函数中:

dataGridSubmissionData.KeyUp += DataGridSubmissionDataOnKeyUp;
            dataGridSubmissionData.BeginningEdit += DataGridSubmissionDataOnBeginningEdit;
            dataGridSubmissionData.CellEditEnding += DataGridSubmissionDataOnCellEditEnding;
            dataGridSubmissionData.CurrentCellChanged += DataGridSubmissionDataOnCurrentCellChanged;

在主体类中:

private bool isCellInEditionMode = false;

 private void DataGridSubmissionDataOnCurrentCellChanged(object sender, EventArgs eventArgs)
        {
            dataGridSubmissionData.BeginEdit();
        }

        private void DataGridSubmissionDataOnCellEditEnding(object sender, DataGridCellEditEndingEventArgs dataGridCellEditEndingEventArgs)
        {
            isCellInEditionMode = false;
        }

        private void DataGridSubmissionDataOnBeginningEdit(object sender, DataGridBeginningEditEventArgs dataGridBeginningEditEventArgs)
        {
            isCellInEditionMode = true;
        }

private void DataGridSubmissionDataOnKeyUp(object sender, KeyEventArgs keyEventArgs)
        {
            if (keyEventArgs.Key == Key.Up || keyEventArgs.Key == Key.Down || keyEventArgs.Key == Key.Left || keyEventArgs.Key == Key.Right)
            {
                if (!isCellInEditionMode)
                    return;

                dataGridSubmissionData.CommitEdit();

                var key = keyEventArgs.Key; // Key to send
                var target = dataGridSubmissionData; // Target element
                var routedEvent = Keyboard.KeyDownEvent; // Event to send

                target.RaiseEvent(
                    new KeyEventArgs(
                        Keyboard.PrimaryDevice,
                        PresentationSource.FromVisual(target),
                        0,
                        key) {RoutedEvent = routedEvent}
                    );
            }
        }

我希望我的回答对某人有所帮助。

this is my solution, which works.

In constructor:

dataGridSubmissionData.KeyUp += DataGridSubmissionDataOnKeyUp;
            dataGridSubmissionData.BeginningEdit += DataGridSubmissionDataOnBeginningEdit;
            dataGridSubmissionData.CellEditEnding += DataGridSubmissionDataOnCellEditEnding;
            dataGridSubmissionData.CurrentCellChanged += DataGridSubmissionDataOnCurrentCellChanged;

In body class:

private bool isCellInEditionMode = false;

 private void DataGridSubmissionDataOnCurrentCellChanged(object sender, EventArgs eventArgs)
        {
            dataGridSubmissionData.BeginEdit();
        }

        private void DataGridSubmissionDataOnCellEditEnding(object sender, DataGridCellEditEndingEventArgs dataGridCellEditEndingEventArgs)
        {
            isCellInEditionMode = false;
        }

        private void DataGridSubmissionDataOnBeginningEdit(object sender, DataGridBeginningEditEventArgs dataGridBeginningEditEventArgs)
        {
            isCellInEditionMode = true;
        }

private void DataGridSubmissionDataOnKeyUp(object sender, KeyEventArgs keyEventArgs)
        {
            if (keyEventArgs.Key == Key.Up || keyEventArgs.Key == Key.Down || keyEventArgs.Key == Key.Left || keyEventArgs.Key == Key.Right)
            {
                if (!isCellInEditionMode)
                    return;

                dataGridSubmissionData.CommitEdit();

                var key = keyEventArgs.Key; // Key to send
                var target = dataGridSubmissionData; // Target element
                var routedEvent = Keyboard.KeyDownEvent; // Event to send

                target.RaiseEvent(
                    new KeyEventArgs(
                        Keyboard.PrimaryDevice,
                        PresentationSource.FromVisual(target),
                        0,
                        key) {RoutedEvent = routedEvent}
                    );
            }
        }

I hope that my answer will help someone.

尘曦 2024-10-17 12:47:04

如果您的案例是 WPF 托管窗口,则它称为无模式 WPF

解决方案可能是这样的:

Window window = new Window();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(window);
window.Show();

我在此处看到了解决方案

If your case is WPF hosted window, it called Modeless WPF.

And the solution might be this:

Window window = new Window();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(window);
window.Show();

I've seen the solution here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文