在WPF中,我有一个带有一些折叠行的DataGrid。当我编辑单元格然后按Enter键时,如果下一行折叠,则选择不会移动到下一个可见行。相反,我刚刚编辑的单元格周围有一个虚线矩形,键入键盘导致完全没有动作。 知道如何让选择跳转到下一个可见行吗? 谢谢
示例(在框架4.0下): xaml:
<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; }
}
}
}
通过编辑行并输入enter,您应该卡在第二行。
答案 0 :(得分:1)
知道如何让选择跳转到下一个可见行吗?
您可以通过处理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); //<---
}
答案 1 :(得分:0)
如果只有一行折叠的行可以跳过,则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答案的修改进行提交,但由于更改了答案的内容,因此该修改被拒绝。因为我没有足够的代表来添加评论,每{{3} },我将更正作为新答案发布。)