DataGridViewComboBoxColumn已设ValueMember,如何通过ID赋值添加行?
DataGridViewComboBox列通过ValueMember赋值报错的解决方法
问题场景
我有一个DataGridView,其中包含一个从SQLite数据库填充的ComboBox列,填充代码如下:
Using conn As New SQLiteConnection(SettingsDbPath()) conn.Open() Dim dt As New DataTable Dim comm As New SQLiteCommand("select calcmaterialid, description from calcmaterial order by description", conn) Dim r As SQLiteDataReader = comm.ExecuteReader() dt.Load(r) Dim cb As DataGridViewComboBoxColumn = CType(dgFrame.Columns("colCalcMatId"), DataGridViewComboBoxColumn) cb.DataSource = dt cb.DisplayMember = "description" cb.ValueMember = "calcmaterialid" End Using
现在需要通过ComboBox单元格的ValueMember(calcmaterialid)为DataGridView添加行,这些ID存储在另一张仅含ID的数据表中。尝试了以下代码:
Dim dr As DataRow For Each dr In dtMeshListFrame.Rows If CInt(dr("colmeshid")) = meshid Then dgFrame.Rows.Add(dr("colamount"), CInt(dr("colcalcmatid")), dr("collengthnet"), dr("collengthgross")) End If Next
执行时出现**"value is not valid"**错误,尝试设置ComboBox文本值、转换为ComboBoxCell赋值均未成功,需要实现基于ValueMember赋值并显示对应DisplayMember的功能。
解决方法
1. 验证赋值ID的有效性
报错核心原因是传入的calcmaterialid值不在ComboBox列绑定的DataTable(dt)的calcmaterialid字段范围内,控件无法匹配对应选项:
- 用SQL排查无效ID:
SELECT colcalcmatid FROM dtMeshListFrame WHERE colcalcmatid NOT IN (SELECT calcmaterialid FROM calcmaterial) - 清理无效数据,或在赋值前过滤掉不存在的ID。
2. 安全的行添加方式
直接使用Rows.Add时,要保证传入值的类型与ComboBox数据源中calcmaterialid的类型完全匹配,也可以通过绑定DataTable的方式实现:
' 构建与dgFrame结构匹配的临时DataTable Dim newDt As New DataTable() newDt.Columns.Add("colamount", GetType(Decimal)) ' 按实际字段类型调整 newDt.Columns.Add("colCalcMatId", GetType(Integer)) newDt.Columns.Add("collengthnet", GetType(Decimal)) newDt.Columns.Add("collengthgross", GetType(Decimal)) For Each dr As DataRow In dtMeshListFrame.Rows If CInt(dr("colmeshid")) = meshid Then Dim targetId = CInt(dr("colcalcmatid")) ' 检查ID是否存在于ComboBox数据源中 Dim isExists = dt.AsEnumerable().Any(Function(row) CInt(row("calcmaterialid")) = targetId) If isExists Then newDt.Rows.Add(dr("colamount"), targetId, dr("collengthnet"), dr("collengthgross")) End If End If Next ' 合并到现有数据源或直接添加行 If dgFrame.DataSource IsNot Nothing Then CType(dgFrame.DataSource, DataTable).Merge(newDt) Else For Each newRow As DataRow In newDt.Rows dgFrame.Rows.Add(newRow.ItemArray) Next End If
3. 逐个单元格赋值(备选)
如果需要单独设置单元格,可先从ComboBox数据源中匹配对应ID,再设置单元格Value属性:
For Each dr As DataRow In dtMeshListFrame.Rows If CInt(dr("colmeshid")) = meshid Then Dim targetId = CInt(dr("colcalcmatid")) Dim matchRow = dt.AsEnumerable().FirstOrDefault(Function(row) CInt(row("calcmaterialid")) = targetId) If matchRow IsNot Nothing Then Dim newRow = dgFrame.Rows.Add() newRow.Cells("colamount").Value = dr("colamount") newRow.Cells("colCalcMatId").Value = targetId newRow.Cells("collengthnet").Value = dr("collengthnet") newRow.Cells("collengthgross").Value = dr("collengthgross") End If End If Next
内容的提问来源于stack exchange,提问作者tosa
相关产品推荐
相关产品推荐

