VB.NET中如何将DataTable图片列正确填充至DataGridView图片列
代码问题分析与修正方案
问题描述
想请教以下代码是否存在问题,以及如何将带有图片列的DataTable正确填充到DataGridView中。
原代码
Private Sub LoadData() Dim item As New List(Of item()) Grid.Bind(item) End Sub Private Sub FillDataTable(Avatar As Image, iRow As Integer, ByVal Codeproduct As String) Dim row As DataRow = _myTable.NewRow() row("") = Avatar row("No") = iRow row("Codeproduct") = Codeproduct _myTable.Rows.Add(row) End Sub Private Sub AddColumnsProgrammatically() Dim Col1 = New DataGridViewImageColumn() Dim Col2 = New DataGridViewTextBoxColumn() Dim Col3 = New DataGridViewTextBoxColumn() Col2.HeaderText = "" Col2.Name = "Column1" Col2.DataPropertyName = "{GetAvatar()}" Col2.HeaderText = "No" Col2.Name = "Column2" Col2.DataPropertyName = "No" Col3.HeaderText = "CodeProduct" Col3.Name = "Column3" Col3.DataPropertyName = "CodeProduct" Grid.Columns.AddRange(New DataGridViewColumn() {Col1, Col2, Col3}) End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load AddColumnsProgrammatically() _myTable.Columns.Add("", GetType(Image())) _myTable.Columns.Add("No", GetType(Integer)) _myTable.Columns.Add("Codeproduct", GetType(String)) LoadData() End Sub Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox1.KeyPress If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Enter) Then Dim iRow As Integer If Grid.RowCount - 1 = 0 Then iRow = 1 Else iRow = Convert.ToInt32(Grid.Rows(Grid.RowCount - 2).Cells(1).Value.ToString()) + 1 End If FillDataTable(avatar, iRow, TextBox1.Text) Grid.DataSource = _myTable TextBox1.Clear() End If End Sub End Class End Class Public Class item Public Property No() As Integer Public Property CodeProduct() As String Public Function GetAvatar() As DataGridViewAvatar Return New DataGridViewAvatar() With { .Value = CType(Me.CodeProduct, String), .Icon = Image.FromFile("money.png") } End Function End Class

代码存在的问题
- 冗余无效代码:
LoadData方法创建空列表且使用非标准绑定方法;item类定义后完全未使用,属于无用代码。 - 列配置错误:
AddColumnsProgrammatically中重复赋值Col2,覆盖初始设置,且图片列Col1未设置DataPropertyName,无法关联DataTable列。- DataTable图片列类型设为
Image()(数组),但实际存储单个Image对象,类型不匹配。
- 行号计算风险:通过
Grid.RowCount计算行号,当DataGridView允许添加新行时,Grid.RowCount - 2可能引发索引越界。 - 重复绑定数据源:每次回车都重新设置
Grid.DataSource = _myTable,导致重复渲染,影响性能且可能重置列状态。 - 未定义变量:调用
FillDataTable时使用的avatar变量未定义,会触发编译错误。
修正后的实现方案
修正步骤
- 清理无用的
LoadData方法和item类。 - 修正DataTable图片列类型为
Image(非数组)。 - 统一配置DataGridView列,确保
DataPropertyName与DataTable列名一致。 - 从DataTable行数计算行号,避免索引越界。
- 仅初始化时绑定一次数据源,后续DataTable更新自动同步。
- 定义并初始化
avatar变量(示例用本地图片路径)。
修正后的完整代码
' 类级别DataTable声明 Private _myTable As New DataTable() ' 示例图片变量,替换为实际路径 Private avatar As Image = Image.FromFile("money.png") Private Sub AddColumnsProgrammatically() ' 图片列配置 Dim imgCol = New DataGridViewImageColumn() imgCol.Name = "AvatarColumn" imgCol.HeaderText = "" imgCol.DataPropertyName = "Avatar" ' 与DataTable列名对应 imgCol.ImageLayout = DataGridViewImageCellLayout.Zoom ' 优化图片显示 ' 序号列 Dim noCol = New DataGridViewTextBoxColumn() noCol.Name = "NoColumn" noCol.HeaderText = "No" noCol.DataPropertyName = "No" ' 产品编码列 Dim codeCol = New DataGridViewTextBoxColumn() codeCol.Name = "CodeColumn" codeCol.HeaderText = "CodeProduct" codeCol.DataPropertyName = "Codeproduct" Grid.Columns.AddRange(New DataGridViewColumn() {imgCol, noCol, codeCol}) End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 初始化DataTable列 _myTable.Columns.Add("Avatar", GetType(Image)) _myTable.Columns.Add("No", GetType(Integer)) _myTable.Columns.Add("Codeproduct", GetType(String)) ' 配置DataGridView列 AddColumnsProgrammatically() ' 仅绑定一次数据源 Grid.DataSource = _myTable End Sub Private Sub FillDataTable(Avatar As Image, iRow As Integer, ByVal Codeproduct As String) Dim row As DataRow = _myTable.NewRow() row("Avatar") = Avatar row("No") = iRow row("Codeproduct") = Codeproduct _myTable.Rows.Add(row) End Sub Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox1.KeyPress If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Enter) Then ' 从DataTable行数计算行号,避免索引越界 Dim iRow As Integer = _myTable.Rows.Count + 1 FillDataTable(avatar, iRow, TextBox1.Text) TextBox1.Clear() End If End Sub End Class
关键说明
- 列绑定一致性:DataGridView列的
DataPropertyName必须与DataTable列名完全匹配,才能自动关联数据。 - 数据源优化:仅初始化时设置一次数据源,后续DataTable的增删改操作会自动同步到DataGridView,无需重复绑定。
- 行号逻辑:使用
_myTable.Rows.Count + 1计算下一行序号,不受DataGridView新行设置影响,逻辑更可靠。 - 图片显示:设置
ImageLayout = Zoom让图片按比例适配单元格,提升显示效果。
内容的提问来源于stack exchange,提问作者roy
相关产品推荐
相关产品推荐

