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

C# WinForms中DataGridView与TextBox绑定DataTable更新异常问题

问题解决方法

核心问题分析

直接将DataTable作为控件数据源时,单元格编辑过程中的数据变更通知无法有效传递到TextBox;同时CellValidating事件触发时机过早,手动调用EndEdit()容易导致数据同步不完整,这就是TextBox无法更新的原因。

具体解决方案

1. 引入BindingSource作为中间层

BindingSource会自动处理数据变更的事件通知,确保所有绑定控件同步感知数据源变化,是WinForms数据绑定的标准最佳实践。

2. 改用CellEndEdit事件处理逻辑

替换CellValidating为CellEndEdit事件,该事件在单元格编辑完全结束、值已提交到数据源后触发,无需手动调用EndEdit(),避免时机问题。

修改后的完整代码

using System;
using System.Data;
using System.Windows.Forms;

namespace TESTING
{
    public partial class Form2 : Form
    {
        private DataTable dt = new DataTable();
        // 添加BindingSource成员
        private BindingSource bs = new BindingSource();

        public Form2()
        {
            InitializeComponent();

            dt.Columns.Add("Field1", typeof(string));
            dt.Columns.Add("Field2", typeof(string));
            dt.Columns.Add("Field3", typeof(string));

            dataGridView1.AllowUserToAddRows = false;
            dataGridView1.AutoGenerateColumns = false;
            // 将BindingSource作为DataGridView的数据源
            bs.DataSource = dt;
            dataGridView1.DataSource = bs;
            dataGridView1.Columns["Column1"].DataPropertyName = "Field1";
            dataGridView1.Columns["Column2"].DataPropertyName = "Field2";

            textBox1.DataBindings.Clear();
            // TextBox绑定到BindingSource的Field3
            textBox1.DataBindings.Add("Text", bs, "Field3");

            dt.Rows.Add();
        }

        // 替换为CellEndEdit事件
        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            switch (dataGridView1.Columns[e.ColumnIndex].Name)
            {
                case "Column1":
                    var currentRow = dt.Rows[e.RowIndex];
                    if (currentRow["Field1"].ToString().Trim() == "123")
                    {
                        currentRow["Field2"] = "123-Column2";
                        currentRow["Field3"] = "123-Column3";
                    }
                    break;
            }
        }

        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
        {
            int icolumn = dataGridView1.CurrentCell.ColumnIndex;
            int irow = dataGridView1.CurrentCell.RowIndex;

            if (keyData == Keys.Enter)
            {
                if (icolumn < dataGridView1.Columns.Count - 1)
                    dataGridView1.CurrentCell = dataGridView1[icolumn + 1, irow];
                else
                    dataGridView1.CurrentCell = dataGridView1[0, irow];

                return true;
            }
            else
                return base.ProcessCmdKey(ref msg, keyData);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            dt.Rows[0]["Field1"] = "123";
            dt.Rows[0]["Field2"] = "123-Column2";
            dt.Rows[0]["Field3"] = "123-Column3";
        }
    }
}

额外说明

  • 不需要再调用this.Refresh(),BindingSource会自动通知所有绑定控件更新。
  • 如果必须保留CellValidating事件(比如需要做输入验证),则需要确保在修改数据源后,调用bs.ResetCurrentItem()来手动触发当前行的变更通知,代码示例:
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
    switch (dataGridView1.Columns[e.ColumnIndex].Name)
    {
        case "Column1":
            // 先完成编辑提交
            if (!dataGridView1.EndEdit()) return;
            var currentRow = dt.Rows[e.RowIndex];
            if (currentRow["Field1"].ToString().Trim() == "123")
            {
                currentRow["Field2"] = "123-Column2";
                currentRow["Field3"] = "123-Column3";
                // 手动通知BindingSource更新当前行
                bs.ResetCurrentItem();
            }
            break;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:03:43