WPF DataGrid 按 Enter 移动到下一个单元格 开启编辑

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>

posted @ 2022-10-31 17:23  slowstart  阅读(208)  评论(0编辑  收藏  举报