C# Winforms中DataGridView价格变动时批量更新关联网格匹配值方案咨询
最优实现方案:DataTable 关联表达式列(无需手动遍历)
核心原理:.NET 的 DataTable 原生支持计算列(Expression 属性)和表间关联(DataRelation),可以直接实现类似 Excel 单元格引用的自动同步效果,所有同步逻辑由 ADO.NET 框架底层处理,性能远高于手动遍历行。
具体实现步骤
步骤1:定义数据源结构并绑定到DataGridView
// 全局声明数据源 DataSet ds = new DataSet(); DataTable dtMaster; // 主商品表 DataTable dtDetail; // 从销售记录表 private void Form1_Load(object sender, EventArgs e) { // 1. 初始化主商品表 dtMaster = new DataTable("MasterItems"); dtMaster.Columns.Add("ITEMNAME", typeof(string)); dtMaster.Columns.Add("PRICE", typeof(decimal)); // 填充示例主表数据 dtMaster.Rows.Add("MOUSE", 399.00m); dtMaster.Rows.Add("PRINTER", 12000.00m); dtMaster.Rows.Add("MONITOR", 18500.00m); // 设置商品名为主键,避免重复商品 dtMaster.PrimaryKey = new DataColumn[] { dtMaster.Columns["ITEMNAME"] }; ds.Tables.Add(dtMaster); // 绑定主网格 dgvMaster.DataSource = dtMaster; // 2. 初始化从销售记录表 dtDetail = new DataTable("SaleRecords"); dtDetail.Columns.Add("CUSTOMERNAME", typeof(string)); dtDetail.Columns.Add("ITEMNAME", typeof(string)); dtDetail.Columns.Add("PRICE", typeof(decimal)); // 填充示例从表数据(仅需填客户名和商品名,价格自动关联) dtDetail.Rows.Add("ANANT H", "MOUSE"); dtDetail.Rows.Add("JOLLY K", "MONITOR"); dtDetail.Rows.Add("ANANT H", "MOUSE"); dtDetail.Rows.Add("KIRAN A", "PRINTER"); dtDetail.Rows.Add("KIRAN A", "MOUSE"); ds.Tables.Add(dtDetail); }
步骤2:建立主从关联,设置从表价格为自动引用列
// 继续放在Form1_Load方法末尾执行 // 建立主从表关联,关联字段为商品名ITEMNAME DataRelation priceRelation = new DataRelation( "ItemPriceRef", dtMaster.Columns["ITEMNAME"], dtDetail.Columns["ITEMNAME"] ); ds.Relations.Add(priceRelation); // 给从表的PRICE列设置关联表达式,自动引用主表的对应价格 dtDetail.Columns["PRICE"].Expression = "Parent(ItemPriceRef).PRICE"; // 绑定从网格 dgvDetail.DataSource = dtDetail;
效果说明
无需编写任何监听主表修改的额外代码,只要主表中任意商品的PRICE值发生变更,从表所有对应商品的PRICE列会自动同步更新,完全匹配你需要的Excel单元格引用效果。底层由ADO.NET直接处理,即使从表有十万级以上数据,同步速度也远快于手动循环遍历匹配。
次优方案(特殊场景无法使用表达式列时选择)
如果业务场景不允许使用计算列,可以用DataView.RowFilter过滤匹配行,避免全表遍历:
// 主网格编辑完成事件 private void dgvMaster_CellEndEdit(object sender, DataGridViewCellEventArgs e) { // 判断是否修改的是价格列 if (e.ColumnIndex == dtMaster.Columns["PRICE"].Ordinal) { string modifiedItem = dtMaster.Rows[e.RowIndex]["ITEMNAME"].ToString(); decimal newPrice = (decimal)dtMaster.Rows[e.RowIndex]["PRICE"]; // 过滤出所有对应商品的行,仅遍历匹配结果 dtDetail.DefaultView.RowFilter = $"ITEMNAME = '{modifiedItem.Replace("'", "''")}'"; foreach (DataRowView row in dtDetail.DefaultView) { row["PRICE"] = newPrice; } dtDetail.DefaultView.RowFilter = ""; } }
内容的提问来源于stack exchange,提问作者Hemal
相关产品推荐
相关产品推荐

