Move Focus to Next Cell on Enter Key Press in WPF DataGrid?
Begin edit mode on key press with DataGridTemplateColumn
WPF中DataGrid按Enter移动到下一个单元格开启编辑。在我的需求里只需要使用模板(DataGridTemplateColumn)的列编辑。
public class DataGridEx : DataGrid
{
public DataGridEx()
{
this.PreviewKeyDown += DataGridEx_PreviewKeyDown;
//当不使用DataGridTemplateColumn时,不需要添加PreparingCellForEdit
this.PreparingCellForEdit += DataGridEx_PreparingCellForEdit;
}
private void DataGridEx_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
FocusFirstControl(e.EditingElement);
}
private void DataGridEx_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
var uiElement = e.OriginalSource as UIElement;
if (e.Key == Key.Enter && uiElement != null)
{
e.Handled = true;
var cell = CurrentCell;
var col = cell.Column.DisplayIndex;
var row = Items.IndexOf(cell.Item);
var index = FindEditableIndex(col);
if (index == -1)
{
if (row + 1 < Items.Count)
{
index = FindEditableIndex(0);
if (index != -1)
{
CurrentCell = new DataGridCellInfo(Items[row + 1], Columns[index]);
BeginEdit();
}
}
}
else
{
CurrentCell = new DataGridCellInfo(cell.Item, Columns[index]);
BeginEdit();
}
}
}
//找到需要修改的列,我这里只有DataGridTemplateColumn需要修改
private int FindEditableIndex(int col)
{
for (int i = col + 1; i < Columns.Count; i++)
{
if (Columns[i] is DataGridTemplateColumn)
{
return i;
}
}
return -1;
}
//DataGridTemplateColumn很复杂的时候,可能需要改动下面的代码
private static bool FocusFirstControl(DependencyObject element)
{
int numVisuals = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < numVisuals; i++)
{
var v = VisualTreeHelper.GetChild(element, i);
var v2 = v as Control;
if (v2 != null)
{
v2.Focus();
if (v is TextBox)
{
((TextBox)v).SelectAll();
}
return true;
}
if (FocusFirstControl(v))
{
return true;
}
}
return false;
}
}
调用的时候 MainWindow.xaml
<Window x:Class="WpfApp1.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"
xmlns:local="clr-namespace:WpfApp1" xmlns:controls="clr-namespace:WpfApp1.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" Name="Window1">
<Window.DataContext>
<local:MainWindowModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="Test" Width="50" Height="25" Command="{Binding TestCommand}"/>
</StackPanel>
<controls:DataGridEx Grid.Row="1" ItemsSource="{Binding Users}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="姓名" Binding="{Binding Name}" IsReadOnly="True"/>
<DataGridTemplateColumn Header="年龄">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</controls:DataGridEx>
</Grid>
</Window>