You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF可编辑DataGrid双向绑定:实现回车键触发值绑定需求

在WPF DataGrid中按下回车键立即更新双向绑定的解决方案

这个问题我做WPF项目时也碰到过,默认的DataGridCell非得失去焦点才会触发双向绑定更新,对用户来说确实有点麻烦。下面给你几个亲测有效的解决方案,按需选就行:

方案1:使用Blend行为(Behavior)实现(推荐,解耦性强)

这种方式通过附加行为来处理回车键事件,不需要修改原有列的类型,复用性很高。

步骤:

  1. 首先确保你的项目引用了行为库:

    • .NET Framework:引用System.Windows.Interactivity(可以通过NuGet安装Microsoft.Expression.Interactions)
    • .NET Core/.NET 5+:安装NuGet包Microsoft.Xaml.Behaviors.Wpf
  2. 创建自定义行为类:

using Microsoft.Xaml.Behaviors.Wpf;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

public class UpdateBindingOnEnterBehavior : Behavior<DataGridCell>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        // 监听单元格的预览按键事件
        AssociatedObject.PreviewKeyDown += OnPreviewKeyDown;
    }

    protected override void OnDetaching()
    {
        // 记得移除事件,避免内存泄漏
        AssociatedObject.PreviewKeyDown -= OnPreviewKeyDown;
        base.OnDetaching();
    }

    private void OnPreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Enter) return;
        
        var cell = sender as DataGridCell;
        if (cell == null || !cell.IsEditing) return;

        // 提交单元格编辑,触发绑定源更新
        cell.CommitEdit();
        // 如果需要自动聚焦到下一个单元格,取消注释下面两行
        // var traversalRequest = new TraversalRequest(FocusNavigationDirection.Next);
        // cell.MoveFocus(traversalRequest);
        
        e.Handled = true; // 阻止事件冒泡
    }
}
  1. 在XAML中使用该行为:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding YourItemCollection}">
    <DataGrid.Columns>
        <DataGridTextColumn 
            Header="Quantity" 
            Binding="{Binding Quantity, UpdateSourceTrigger=LostFocus}">
            <DataGridTextColumn.CellStyle>
                <Style TargetType="DataGridCell">
                    <Setter Property="behaviors:Interaction.Behaviors">
                        <Setter.Value>
                            <local:UpdateBindingOnEnterBehavior />
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
        <!-- 其他列配置 -->
    </DataGrid.Columns>
</DataGrid>

注意:XAML中需要添加命名空间xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"和自定义类的命名空间xmlns:local="clr-namespace:YourProjectNamespace"

方案2:自定义DataGridTextColumn

如果你想直接针对特定列做定制,可以继承DataGridTextColumn,重写编辑元素的生成逻辑,添加回车键处理。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

public class AutoUpdateTextColumn : DataGridTextColumn
{
    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        var textBox = base.GenerateEditingElement(cell, dataItem) as TextBox;
        if (textBox != null)
        {
            textBox.KeyDown += TextBox_KeyDown;
        }
        return textBox;
    }

    private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Enter) return;
        
        var textBox = sender as TextBox;
        if (textBox == null) return;

        // 直接更新绑定源
        var bindingExpr = textBox.GetBindingExpression(TextBox.TextProperty);
        bindingExpr?.UpdateSource();
        
        // 结束单元格编辑
        var cell = textBox.Parent as DataGridCell;
        cell?.CommitEdit();
        
        e.Handled = true;
    }
}

在XAML中直接使用这个自定义列:

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding YourItemCollection}">
    <DataGrid.Columns>
        <local:AutoUpdateTextColumn 
            Header="Quantity" 
            Binding="{Binding Quantity}" />
        <!-- 其他列 -->
    </DataGrid.Columns>
</DataGrid>

方案3:附加属性实现全局处理

如果想让整个DataGrid的所有可编辑列都支持回车更新,可以用附加属性来全局配置:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

public static class DataGridHelper
{
    public static readonly DependencyProperty UpdateBindingOnEnterProperty =
        DependencyProperty.RegisterAttached(
            "UpdateBindingOnEnter",
            typeof(bool),
            typeof(DataGridHelper),
            new PropertyMetadata(false, OnUpdateBindingOnEnterChanged));

    public static bool GetUpdateBindingOnEnter(DependencyObject obj)
    {
        return (bool)obj.GetValue(UpdateBindingOnEnterProperty);
    }

    public static void SetUpdateBindingOnEnter(DependencyObject obj, bool value)
    {
        obj.SetValue(UpdateBindingOnEnterProperty, value);
    }

    private static void OnUpdateBindingOnEnterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = d as DataGrid;
        if (dataGrid == null) return;

        if ((bool)e.NewValue)
        {
            dataGrid.PreviewKeyDown += DataGrid_PreviewKeyDown;
        }
        else
        {
            dataGrid.PreviewKeyDown -= DataGrid_PreviewKeyDown;
        }
    }

    private static void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Enter) return;
        
        var dataGrid = sender as DataGrid;
        var cell = dataGrid.CurrentCell.Item as DataGridCell;
        if (cell != null && cell.IsEditing)
        {
            cell.CommitEdit();
            e.Handled = true;
        }
    }
}

XAML中使用:

<DataGrid 
    AutoGenerateColumns="False" 
    ItemsSource="{Binding YourItemCollection}"
    local:DataGridHelper.UpdateBindingOnEnter="True">
    <!-- 列配置 -->
</DataGrid>

内容的提问来源于stack exchange,提问作者Sarathi Jayapal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:22:53