VB.NET中无需关闭子窗体时同步更新主窗体DataGridView绑定源
VB.NET 跨窗体DataGridView数据同步刷新解决方案
问题核心
子窗体更新产品数据后,主窗体DataGridView仅能通过事件刷新当前行,新增行调用同一产品时仍显示旧的Prp值——根源在于数据源未被全局更新,仅刷新了UI而非修改底层共享数据集,新增行读取的仍是旧数据副本。
解决方案思路
- 让子窗体直接操作主窗体的共享数据源(
DataTable/BindingSource),而非复制数据; - 子窗体更新完成后,批量修改数据源中所有匹配产品的行;
- 触发事件通知主窗体调用
ResetBindings刷新整个DataGridView,确保所有行(含新增行)同步最新数据。
完整代码实现
主窗体(autocompledatagridview)
Public Class autocompledatagridview Private productBindingSource As New BindingSource() Private productDataTable As DataTable Private Sub autocompledatagridview_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 初始化产品数据表结构 productDataTable = New DataTable("Products") productDataTable.Columns.Add("ProductId", GetType(Integer)) productDataTable.Columns.Add("ProductName", GetType(String)) productDataTable.Columns.Add("Prp", GetType(Decimal)) ' 加载测试初始数据 productDataTable.Rows.Add(1, "产品A", 100.0) productDataTable.Rows.Add(2, "产品B", 200.0) ' 绑定到DataGridView productBindingSource.DataSource = productDataTable DataGridView1.DataSource = productBindingSource End Sub ' 打开编辑产品子窗体按钮事件 Private Sub btnEditProduct_Click(sender As Object, e As EventArgs) Handles btnEditProduct.Click If DataGridView1.CurrentRow IsNot Nothing Then Dim selectedRow As DataRowView = DirectCast(productBindingSource.Current, DataRowView) Dim editForm As New formproduct(productBindingSource, selectedRow.Row) AddHandler editForm.ProductUpdated, AddressOf RefreshProductData editForm.ShowDialog() RemoveHandler editForm.ProductUpdated, AddressOf RefreshProductData End If End Sub ' 刷新数据源并同步UI Private Sub RefreshProductData() ' 通知DataGridView刷新所有行的绑定数据 productBindingSource.ResetBindings(False) End Sub ' 新增行(模拟调用同一产品)按钮事件 Private Sub btnAddRow_Click(sender As Object, e As EventArgs) Handles btnAddRow.Click ' 从共享数据源获取最新的产品A数据 Dim targetProduct = productDataTable.Select("ProductId=1")(0) Dim newRow As DataRow = productDataTable.NewRow() newRow("ProductId") = targetProduct("ProductId") newRow("ProductName") = targetProduct("ProductName") newRow("Prp") = targetProduct("Prp") productDataTable.Rows.Add(newRow) productBindingSource.ResetBindings(False) End Sub End Class
子窗体(formproduct)
Public Class formproduct ' 定义更新完成事件,用于通知主窗体 Public Event ProductUpdated() Private currentProductRow As DataRow Private productBS As BindingSource ' 构造函数:接收主窗体的数据源和当前编辑行 Public Sub New(bs As BindingSource, targetRow As DataRow) InitializeComponent() productBS = bs currentProductRow = targetRow ' 绑定当前行数据到编辑控件 txtProductId.Text = currentProductRow("ProductId").ToString() txtProductName.Text = currentProductRow("ProductName").ToString() txtPrp.Text = currentProductRow("Prp").ToString() End Sub ' 保存修改按钮事件 Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click Dim updatedPrp = Decimal.Parse(txtPrp.Text) Dim updatedName = txtProductName.Text Dim productId = Integer.Parse(txtProductId.Text) ' 批量更新数据源中所有匹配该产品ID的行 Dim productTable = DirectCast(productBS.DataSource, DataTable) For Each row As DataRow In productTable.Select($"ProductId={productId}") row("ProductName") = updatedName row("Prp") = updatedPrp Next ' 触发事件通知主窗体刷新 RaiseEvent ProductUpdated() Me.Close() End Sub End Class
效果演示
- 初始状态:主窗体DataGridView显示产品A(
Prp=100)、产品B(Prp=200); - 编辑产品:点击编辑产品A,在子窗体将
Prp修改为150并保存,主窗体中所有产品A的行立即更新为Prp=150; - 新增行测试:点击新增行按钮,新增的产品A行自动获取最新的
Prp=150,而非旧值100。
关键注意事项
- 共享数据源:子窗体必须操作主窗体的数据源实例,避免数据副本导致的同步失效;
- 批量更新:若主窗体存在多行引用同一产品,需遍历数据集更新所有匹配行,确保新增行读取的是最新数据;
- ResetBindings:调用
BindingSource.ResetBindings(False)强制DataGridView刷新所有行的绑定数据,而非仅当前行。
内容的提问来源于stack exchange,提问作者dlaksmi
相关产品推荐
相关产品推荐

