使用隐藏行编辑 DataGrid 中的单元格
Posted
技术标签:
【中文标题】使用隐藏行编辑 DataGrid 中的单元格【英文标题】:Edit cells in DataGrid with hidden rows 【发布时间】: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;
通过编辑行并输入回车,您应该会卡在第二行。
【问题讨论】:
请在提问时提供一个最小、完整和可验证的问题示例:***.com/help/mcve 添加了这种行为的例子 【参考方案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,我将更正作为新答案发布。)
【讨论】:
以上是关于使用隐藏行编辑 DataGrid 中的单元格的主要内容,如果未能解决你的问题,请参考以下文章
无法编辑我的 DataGrid WPF Framework 4.5 的单元格