【问题标题】:Edit cells in DataGrid with hidden rows使用隐藏行编辑 DataGrid 中的单元格
【发布时间】:2017-10-23 17:16:45
【问题描述】:

在 WPF 中,我有一个带有一些折叠行的 DataGrid。当我编辑一个单元格然后按 Enter 键时,如果下一行已折叠,则选择不会移动到下一个可见行。相反,我刚刚编辑过的单元格周围是一个虚线矩形,并且键入键盘根本不会导致任何操作。 知道如何使选择跳转到下一个可见行吗? 谢谢

示例(在框架 4.0 下): xml:

<Window x:Class="WpfDataGridEdit.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <DataGrid AutoGenerateColumns="False" Name="dataGrid">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=Value1}"/>
            <DataGridTextColumn Binding="{Binding Path=Value2}"/>
        </DataGrid.Columns>
        <DataGrid.RowStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <Setter Property="Visibility" Value="{Binding Visibility}" />
            </Style>
        </DataGrid.RowStyle>
    </DataGrid>
</Window>

背后的代码:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WpfDataGridEdit
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Row> rows = new List<Row>();

        public MainWindow()
        {
            InitializeComponent();

            for (int i = 0; i < 10; i++)
                this.rows.Add(new Row { Value1 = i.ToString(), Value2 = "x", Visibility = i % 3 == 0 ? Visibility.Collapsed : Visibility.Visible });

            this.dataGrid.ItemsSource = this.rows;
        }
    }

    public class Row
    {
        private string value1;
        public string Value1
        {
            get { return this.value1; }
            set { this.value1 = value; }
        }

        private string value2;
        public string Value2
        {
            get { return this.value2; }
            set { this.value2 = value; }
        }

        private Visibility visibility;
        public Visibility Visibility
        {
            get { return this.visibility; }
            set { this.visibility = value; }
        }
    }
}

通过编辑行并输入回车,您应该会卡在第二行。

【问题讨论】:

标签: wpf datagrid cell visibility edit


【解决方案1】:

知道如何使选择跳转到下一个可见行吗?

此行为已被报告为错误:https://connect.microsoft.com/VisualStudio/feedback/details/526014/keyboard-navigation-doesnt-work-when-the-wpf-datagrid-has-collapsed-or-hidden-rows

您可以通过处理 DataGrid 的 PreviewKeyDown 事件来绕过它,如下所示:

private void dataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        e.Handled = true;
        DataGrid dg = sender as DataGrid;
        int index = dg.SelectedIndex;
        if (index < dg.Items.Count - 1)
        {
            dg.SelectedIndex++;
            DataGridRow nextRow = dg.ItemContainerGenerator.ContainerFromIndex(dg.SelectedIndex) as DataGridRow;
            while (nextRow != null && nextRow.Visibility == Visibility.Collapsed)
                nextRow = dg.ItemContainerGenerator.ContainerFromIndex(dg.SelectedIndex + 1) as DataGridRow;

            if (nextRow != null)
            {
                dg.SelectedItem = nextRow.DataContext;
                dg.CurrentCell = new DataGridCellInfo(nextRow.DataContext, dg.Columns[0]);
            }
        }
    }
}

编辑:您可能还希望通过将事件处理程序连接到BeginningEdit 事件来保存当前编辑列的索引:

DataGridColumn _lastEditedColumn;
private void dataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
    DataGrid dg = sender as DataGrid;
    _lastEditedColumn = dg.CurrentCell.Column;
}

..并将CurrentCell 设置为此:

if (nextRow != null)
{
    dg.SelectedItem = nextRow.DataContext;
    dg.CurrentCell = new DataGridCellInfo(nextRow.DataContext, _lastEditedColumn); //<---
}

【讨论】:

  • 这仅适用于我给出的示例,因为它只有一列。在多列数据网格中,这将导致焦点向右移动,而不是在编辑单元格下方。
  • 这就是我要求您提供问题的完整回购的原因之一。显然你没有。
  • 另请注意,此行为已被报告为错误:connect.microsoft.com/VisualStudio/feedback/details/526014/…
  • 虽然也与隐藏行有关,但这是一个不同的错误。
  • 请看我编辑的答案。它应该让您了解如何解决这个问题。
【解决方案2】:

如果您只有一个折叠行可以跳过,mm8 的答案是完美的。相邻行折叠时,代码进入无限循环。

当获取下一行时,代码应该增加 selectedIndex 而不是将 1 添加到相同的值。

即将dg.SelectedIndex + 1 替换为++dg.SelectedIndex

像这样:

private void dataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        e.Handled = true;
        DataGrid dg = sender as DataGrid;
        int index = dg.SelectedIndex;
        if (index < dg.Items.Count - 1)
        {
            dg.SelectedIndex++;
            DataGridRow nextRow = dg.ItemContainerGenerator.ContainerFromIndex(dg.SelectedIndex) as DataGridRow;
            while (nextRow != null && nextRow.Visibility == Visibility.Collapsed)
                nextRow = dg.ItemContainerGenerator.ContainerFromIndex(++dg.SelectedIndex) as DataGridRow;

            if (nextRow != null)
            {
                dg.SelectedItem = nextRow.DataContext;
                dg.CurrentCell = new DataGridCellInfo(nextRow.DataContext, dg.Columns[0]);
            }
        }
    }
}

注意:通过将 DataGrid 的 SelectedIndex 推进到折叠的行,DataGrid 上的任何 SelectedCellsChanged 或 SelectionChanged 事件都会触发。根据应用程序在这些事件中的作用,这可能不适合您的应用程序。

如果是这种情况,您可能需要考虑使用变量来保存索引,如下所示:

private void dataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        e.Handled = true;
        DataGrid dg = sender as DataGrid;
        int index = dg.SelectedIndex;
        int maxIndex = dg.Items.Count - 1;

        while (index < maxIndex
            && (dg.ItemContainerGenerator.ContainerFromIndex(++index) as DataGridRow)?.Visibility == Visibility.Collapsed)
        {
        }

        if ((dg.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow)?.Visibility == Visibility.Visible)
        {
            dg.SelectedIndex = index;
        }
    }
}

空的while循环是故意的,因为索引在条件中是先进的。 (我不喜欢这种代码风格,但它有效)

(背景:我尝试将此更正作为对 mm8 答案的编辑提交,但因为它更改了答案的内容,所以编辑被拒绝。因为我没有足够的代表来添加评论,每 advice on editing,我将更正作为新答案发布。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多