VB.NET中DataTable空值列查询及跨窗体DataGrid数据同步异常排查
问题描述
我想通过DataTable Select实现从Form2的DataGridView(数据源为DataTable)到Form1的DataGridView(数据源为DataTable)的数据变更操作,但Form1中DataGridView的显示结果与预期不符,怀疑代码存在问题。

预期结果
| Column1 | Column2 | Column3 | Column4 | Qty |
|---|---|---|---|---|
| 001 | TEST1 | TEST1 | TEST1 | 1 |
| 001 | TEST1 | TEST1 | 1 | |
| 001 | TEST1 | 1 | ||
| 001 | TEST1 | TEST1 | 1 | |
| 002 | TEST2 | TEST2 | TEST2 | 1 |
现有代码
Form1代码
Public Class Form1 Private table1 As New DataTable Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load table1.Columns.Add(New DataColumn("Column1", GetType(String))) table1.Columns.Add(New DataColumn("Column2", GetType(String))) table1.Columns.Add(New DataColumn("Column3", GetType(String))) table1.Columns.Add(New DataColumn("Column4", GetType(String))) table1.Columns.Add(New DataColumn("Qty", GetType(Integer))) DataGridView1.DataSource = table1 End Sub Private Sub BTNAdd_Click(sender As Object, e As EventArgs) Handles BTNAdd.Click Dim Column2 As String = TextBox2.Text.Trim() Dim Column1 = TextBox1.Text.Trim() Using frm = New Form2(Column2) If frm.ShowDialog() = DialogResult.OK Then Dim datarow As DataRow = Nothing Dim Column3 = frm.DataGridView1.CurrentRow.Cells(3).Value?.ToString() Dim Column4 = frm.DataGridView1.CurrentRow.Cells(4).Value?.ToString() If table1.Rows.Cast(Of DataRow).Any() Then datarow = table1.Select($"Column1 = '{Column1}' AND Column2 = '{Column2}' AND Column3 = '{Column3}' OR Column3 IS NULL AND Column4 = '{Column4}' OR Column4 IS NULL").FirstOrDefault() End If If datarow IsNot Nothing Then Dim qty = If(datarow("Qty") Is DBNull.Value, 0, datarow.Field(Of Integer)("Qty")) datarow.SetField("Qty", qty + 1) Return Else End If Try For Each row2 As DataGridViewRow In frm.DataGridView1.Rows Dim isselect As Boolean = Convert.ToBoolean(row2.Cells("checkboxcolumn").Value) If isselect Then table1.Rows.Add(Column1, Column2, Column3, Column4, 1) TextBox1.Clear() TextBox2.Clear() End If Next Catch ex As Exception MessageBox.Show(ex.Message) End Try Else Return End If End Using End Sub End Class
Form2代码
Public Class Form2 Sub New() InitializeComponent() End Sub Public Function ConvertToList(Of T)(ByVal dt As DataTable) As List(Of T) Dim columnNames = dt.Columns.Cast(Of DataColumn)().Select(Function(c) c.ColumnName).ToList() Dim properties = GetType(T).GetProperties() Return dt.AsEnumerable().Select(Function(row) Dim objT = Activator.CreateInstance(Of T)() For Each pro In properties If columnNames.Contains(pro.Name) Then Dim pI As PropertyInfo = objT.GetType().GetProperty(pro.Name) pro.SetValue(objT, If(row(pro.Name) Is DBNull.Value, Nothing, Convert.ChangeType(row(pro.Name), pI.PropertyType))) End If Next pro Return objT End Function).ToList() End Function Public Sub New(Column2 As String) Me.New Dim table2 As New DataTable("Players") table2.Columns.Add(New DataColumn("Column1", GetType(String))) table2.Columns.Add(New DataColumn("Column2", GetType(String))) table2.Columns.Add(New DataColumn("Column3", GetType(String))) table2.Columns.Add(New DataColumn("Column4", GetType(String))) table2.Rows.Add("001", "TEST1", "TEST1", "TEST1") table2.Rows.Add("001", "TEST1", "TEST1", "") table2.Rows.Add("001", "TEST1", "", "") table2.Rows.Add("001", "TEST1", "", "TEST1") table2.Rows.Add("002", "TEST2", "", "TEST2") DataGridView1.DataSource = ConvertToList(Of Table2)(table2) Dim CheckedBoxColumn As New DataGridViewCheckBoxColumn CheckedBoxColumn.Width = 40 CheckedBoxColumn.Name = "checkboxcolumn" CheckedBoxColumn.HeaderText = "Check" DataGridView1.Columns.Insert(0, CheckedBoxColumn) End Sub Private Sub BtnOK_Click(sender As Object, e As EventArgs) Handles BtnOK.Click DialogResult = DialogResult.OK End Sub End Class Public Class Table2 Public Property Column1() As String Public Property Column2() As String Public Property Column3() As String Public Property Column4() As String End Class
问题分析与修复方案
核心问题1:Select语句逻辑错误
当前table1.Select的条件存在运算符优先级混乱,OR优先级低于AND,导致匹配逻辑完全偏离预期;同时Form2中存储的是空字符串"",但代码用Column3 IS NULL无法匹配空字符串(空字符串和DBNull是不同概念)。
核心问题2:选中行数据获取错误
代码仅提取了CurrentRow的Column3/Column4值,循环所有选中行时重复使用该值,导致所有选中行都被添加为同一数据,而非各自的行数据。
修复后的Form1代码
Public Class Form1 Private table1 As New DataTable Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load table1.Columns.Add(New DataColumn("Column1", GetType(String))) table1.Columns.Add(New DataColumn("Column2", GetType(String))) table1.Columns.Add(New DataColumn("Column3", GetType(String))) table1.Columns.Add(New DataColumn("Column4", GetType(String))) table1.Columns.Add(New DataColumn("Qty", GetType(Integer))) DataGridView1.DataSource = table1 End Sub Private Sub BTNAdd_Click(sender As Object, e As EventArgs) Handles BTNAdd.Click Dim Column2 As String = TextBox2.Text.Trim() Dim Column1 = TextBox1.Text.Trim() Using frm = New Form2(Column2) If frm.ShowDialog() = DialogResult.OK Then Try For Each row2 As DataGridViewRow In frm.DataGridView1.Rows ' 跳过DataGridView自动生成的空白新行 If row2.IsNewRow Then Continue For Dim isselect As Boolean = Convert.ToBoolean(row2.Cells("checkboxcolumn").Value) If isselect Then ' 获取当前选中行的真实数据 Dim rowColumn1 = row2.Cells(1).Value?.ToString() Dim rowColumn2 = row2.Cells(2).Value?.ToString() Dim rowColumn3 = row2.Cells(3).Value?.ToString() Dim rowColumn4 = row2.Cells(4).Value?.ToString() ' 修正过滤条件:精准匹配所有列,兼容空字符串 Dim filter As String = $"Column1 = '{rowColumn1}' AND Column2 = '{rowColumn2}' " & $"AND (Column3 = '{If(String.IsNullOrEmpty(rowColumn3), "", rowColumn3)}' OR Column3 = '') " & $"AND (Column4 = '{If(String.IsNullOrEmpty(rowColumn4), "", rowColumn4)}' OR Column4 = '')" Dim matchRows = table1.Select(filter) If matchRows.Any() Then ' 找到匹配行,数量+1 Dim qty = If(matchRows(0)("Qty") Is DBNull.Value, 0, matchRows(0).Field(Of Integer)("Qty")) matchRows(0).SetField("Qty", qty + 1) Else ' 无匹配行,新增数据 table1.Rows.Add(rowColumn1, rowColumn2, rowColumn3, rowColumn4, 1) End If End If Next TextBox1.Clear() TextBox2.Clear() Catch ex As Exception MessageBox.Show(ex.Message) End Try Else Return End If End Using End Sub End Class
优化说明
- 移除无效的
CurrentRow数据提取,直接遍历选中行时获取对应单元格的真实数据 - 修正Select过滤条件,准确匹配空字符串,确保逻辑符合预期
- 添加空白新行判断,避免处理DataGridView自动生成的无效行
- 调整数据处理逻辑,保证每一行选中数据都被独立处理,不会重复添加同一内容
内容的提问来源于stack exchange,提问作者roy
相关产品推荐
相关产品推荐

