跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

【Vb.net】DataGridView 所有数据绑定方式详解 (VB.NET, VS2010)

DataGridView 所有数据绑定方式详解 (VB.NET, VS2010) DataGridView 提供了多种数据绑定方式,以下是完整的绑定方法分类和详细说明: 一、基本数据绑定方式 1. 绑定 DataTable

' 创建DataTable

Dim dt As New DataTable("Products") dt.Columns.Add("ID", GetType(Integer)) dt.Columns.Add("Name", GetType(String)) dt.Columns.Add("Price", GetType(Decimal))

' 添加数据 dt.Rows.Add(1, "笔记本电脑", 5999.99) dt.Rows.Add(2, "智能手机", 2999.99)

' 直接绑定 dgv.DataSource = dt

' 优点:简单直接,自动生成列 ' 缺点:列顺序和格式控制较弱

2. 绑定 DataView

' 从DataTable创建DataView

Dim dv As New DataView(dt)

' 设置过滤和排序 dv.RowFilter = "Price > 2000" dv.Sort = "Price DESC"

' 绑定DataView dgv.DataSource = dv

' 优点:支持过滤和排序 ' 缺点:需要先有DataTable

3. 绑定 DataSet

' 创建DataSet并添加多个DataTable

Dim ds As New DataSet("Inventory") ds.Tables.Add(dt) ' 添加前面创建的Products表 ds.Tables.Add(New DataTable("Categories")) ' 添加另一个表

' 绑定指定表 dgv.DataSource = ds dgv.DataMember = "Products"

' 优点:适合多表数据 ' 缺点:稍复杂

4. 绑定 List(Of T)

' 定义实体类

Public Class Product Public Property ID As Integer Public Property Name As String Public Property Price As Decimal End Class

' 创建列表 Dim products As New List(Of Product)() products.Add(New Product With {.ID = 1, .Name = "笔记本电脑", .Price = 5999.99}) products.Add(New Product With {.ID = 2, .Name = "智能手机", .Price = 2999.99})

' 绑定列表 dgv.DataSource = products

' 优点:强类型,面向对象 ' 缺点:需要自定义列时需设置AutoGenerateColumns=False

5. 绑定数组

' 创建对象数组

Dim productsArray As Object() = { New With {.ID = 1, .Name = "笔记本电脑", .Price = 5999.99}, New With {.ID = 2, .Name = "智能手机", .Price = 2999.99} }

' 绑定数组 dgv.DataSource = productsArray

' 优点:简单快速 ' 缺点:匿名类型,后期维护困难

二、高级数据绑定方式 1. 使用 BindingSource 中间层

' 创建BindingSource

Dim bs As New BindingSource()

' 设置数据源 bs.DataSource = products ' 可以是List/DataTable等

' 绑定到DataGridView dgv.DataSource = bs

' 数据操作通过BindingSource bs.Add(New Product With {.ID = 3, .Name = "平板电脑", .Price = 1999.99}) bs.RemoveAt(0)

' 优点:解耦数据源和控件,支持更多功能 ' 缺点:增加一层间接性

2. 自定义对象绑定 (实现 ITypedList/IListSource)

' 自定义集合类实现ITypedList

Public Class ProductCollection Implements ITypedList, IList

Private _products As New List(Of Product)()

' 实现必要接口方法...

Public Function GetItemProperties(properties As PropertyDescriptorCollection) As PropertyDescriptorCollection _ Implements ITypedList.GetItemProperties Return TypeDescriptor.GetProperties(GetType(Product)) End Function

' 其他方法... End Class

' 使用自定义集合 Dim customProducts As New ProductCollection() customProducts.Add(New Product With {.ID = 1, .Name = "笔记本电脑", .Price = 5999.99})

' 绑定 dgv.DataSource = customProducts

' 优点:完全控制数据绑定行为 ' 缺点:实现复杂

3. 虚拟模式绑定 (超大数据集)

' 启用虚拟模式

dgv.VirtualMode = True dgv.RowCount = 1000000 ' 设置总行数

' 处理数据获取事件 Private Sub dgv_CellValueNeeded(sender As Object, e As DataGridViewCellValueEventArgs) ' 根据需要从数据库或其他源获取数据 e.Value = GetDataFromDatabase(e.RowIndex, e.ColumnIndex) End Sub

' 处理数据更新事件 Private Sub dgv_CellValuePushed(sender As Object, e As DataGridViewCellValueEventArgs) UpdateDataInDatabase(e.RowIndex, e.ColumnIndex, e.Value) End Sub

' 优点:处理超大数据集 ' 缺点:实现复杂,需要手动管理数据

4. 分层数据绑定 (主从表)

' 主表DataGridView

dgvMaster.DataSource = ds dgvMaster.DataMember = "Departments"

' 从表DataGridView dgvDetail.DataSource = ds dgvDetail.DataMember = "Departments.DepartmentEmployees"

' 或者使用BindingSource建立关系 Dim bsDept As New BindingSource(ds, "Departments") Dim bsEmp As New BindingSource(bsDept, "DepartmentEmployees")

dgvMaster.DataSource = bsDept dgvDetail.DataSource = bsEmp

' 优点:显示关联数据 ' 缺点:需要正确设置数据关系

三、自定义列绑定方法 1. 手动添加列并绑定

' 禁止自动生成列

dgv.AutoGenerateColumns = False

' 手动添加列 Dim colID As New DataGridViewTextBoxColumn() colID.Name = "colID" colID.DataPropertyName = "ID" ' 绑定到数据源的ID属性 colID.HeaderText = "产品ID" dgv.Columns.Add(colID)

Dim colName As New DataGridViewTextBoxColumn() colName.Name = "colName" colName.DataPropertyName = "Name" colName.HeaderText = "产品名称" dgv.Columns.Add(colName)

' 绑定数据 dgv.DataSource = products

' 优点:完全控制列显示 ' 缺点:需要手动设置每列

2. 自定义列类型绑定

' 添加图像列

Dim imgCol As New DataGridViewImageColumn() imgCol.Name = "colImage" imgCol.DataPropertyName = "ImageData" ' 绑定到字节数组或Image类型属性 imgCol.ImageLayout = DataGridViewImageCellLayout.Zoom dgv.Columns.Add(imgCol)

' 添加按钮列 Dim btnCol As New DataGridViewButtonColumn() btnCol.Name = "colAction" btnCol.HeaderText = "操作" btnCol.Text = "查看" btnCol.UseColumnTextForButtonValue = True dgv.Columns.Add(btnCol)

' 添加组合框列 Dim cmbCol As New DataGridViewComboBoxColumn() cmbCol.Name = "colCategory" cmbCol.DataPropertyName = "CategoryID" ' 绑定到值字段 cmbCol.DisplayMember = "CategoryName" ' 显示文本字段 cmbCol.ValueMember = "CategoryID" ' 值字段 cmbCol.DataSource = GetCategories() ' 数据源 dgv.Columns.Add(cmbCol)

3. 动态列绑定

' 根据运行时条件创建列

Public Sub BindDataWithDynamicColumns(data As Object, Optional includeColumns As String() = Nothing) dgv.Columns.Clear()

' 获取数据类型的属性 Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(data.GetType().GetGenericArguments()(0))

For Each prop As PropertyDescriptor In props ' 如果指定了包含列且当前列不在其中,则跳过 If includeColumns IsNot Nothing AndAlso Not includeColumns.Contains(prop.Name) Then Continue For End If

' 根据属性类型创建不同列 If prop.PropertyType Is GetType(Boolean) Then Dim col As New DataGridViewCheckBoxColumn() col.Name = "col" & prop.Name col.DataPropertyName = prop.Name col.HeaderText = prop.Name dgv.Columns.Add(col) ElseIf prop.PropertyType Is GetType(DateTime) Then Dim col As New DataGridViewTextBoxColumn() col.Name = "col" & prop.Name col.DataPropertyName = prop.Name col.HeaderText = prop.Name col.DefaultCellStyle.Format = "yyyy-MM-dd" dgv.Columns.Add(col) Else Dim col As New DataGridViewTextBoxColumn() col.Name = "col" & prop.Name col.DataPropertyName = prop.Name col.HeaderText = prop.Name dgv.Columns.Add(col) End If Next

' 绑定数据 dgv.DataSource = data End Sub

' 使用示例 BindDataWithDynamicColumns(products, {"ID", "Name", "Price"})

四、数据绑定最佳实践 1. 性能优化绑定

' 大数据量绑定优化

Public Sub BindLargeData(data As IList) ' 禁用自动操作 dgv.SuspendLayout() dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None

' 使用BindingSource Dim bs As New BindingSource() bs.DataSource = data dgv.DataSource = bs

' 恢复自动操作 dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells dgv.ResumeLayout() End Sub

2. 双向数据绑定

' 设置双向绑定

Public Sub SetupTwoWayBinding() ' 使用BindingSource Dim bs As New BindingSource() bs.DataSource = GetProducts() dgv.DataSource = bs

' 手动列设置 dgv.AutoGenerateColumns = False

' ID列 (只读) Dim colID As New DataGridViewTextBoxColumn() colID.DataPropertyName = "ID" colID.ReadOnly = True dgv.Columns.Add(colID)

' 可编辑列 Dim colName As New DataGridViewTextBoxColumn() colName.DataPropertyName = "Name" colName.ReadOnly = False dgv.Columns.Add(colName)

' 保存按钮 Dim btnSave As New DataGridViewButtonColumn() btnSave.Text = "保存" btnSave.UseColumnTextForButtonValue = True dgv.Columns.Add(btnSave)

' 处理单元格值变化 AddHandler dgv.CellValueChanged, AddressOf dgv_CellValueChanged AddHandler dgv.CellContentClick, AddressOf dgv_CellContentClick End Sub

Private Sub dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) ' 自动更新数据源 Dim bs As BindingSource = CType(dgv.DataSource, BindingSource) bs.EndEdit() End Sub

Private Sub dgv_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) If e.ColumnIndex = dgv.Columns("btnSave").Index Then SaveChanges() End If End Sub

Private Sub SaveChanges() Dim bs As BindingSource = CType(dgv.DataSource, BindingSource) Dim products As List(Of Product) = CType(bs.DataSource, List(Of Product))

' 保存到数据库 Using db As New DbContext() For Each product In products db.UpdateProduct(product) Next db.SaveChanges() End Using

MessageBox.Show("保存成功!") End Sub

3. 数据验证绑定

' 设置数据验证

Public Sub SetupDataValidation() dgv.DataSource = GetProducts()

' 处理数据验证事件 AddHandler dgv.DataError, AddressOf dgv_DataError AddHandler dgv.CellValidating, AddressOf dgv_CellValidating End Sub

Private Sub dgv_DataError(sender As Object, e As DataGridViewDataErrorEventArgs) MessageBox.Show($"数据错误: {e.Exception.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error) End Sub

Private Sub dgv_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) If dgv.Columns(e.ColumnIndex).Name = "colPrice" Then If Not Decimal.TryParse(e.FormattedValue.ToString(), Nothing) Then e.Cancel = True MessageBox.Show("价格必须是有效数字", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning) End If End If End Sub

五、特殊数据源绑定 1. 绑定 XML 数据

' 从XML文件加载数据

Public Sub BindXmlData(xmlFile As String) Dim ds As New DataSet() ds.ReadXml(xmlFile)

dgv.DataSource = ds dgv.DataMember = ds.Tables(0).TableName End Sub

2. 绑定 JSON 数据

' 使用Json.NET绑定JSON数据

Public Sub BindJsonData(jsonString As String) Dim products = JsonConvert.DeserializeObject(Of List(Of Product))(jsonString) dgv.DataSource = products End Sub

3. 绑定数据库存储过程结果

' 绑定存储过程结果

Public Sub BindStoredProcedureResults() Using conn As New SqlConnection(connectionString) Using cmd As New SqlCommand("usp_GetProducts", conn) cmd.CommandType = CommandType.StoredProcedure cmd.Parameters.AddWithValue("@CategoryID", 1)

Dim adapter As New SqlDataAdapter(cmd) Dim dt As New DataTable() adapter.Fill(dt)

dgv.DataSource = dt End Using End Using End Sub

六、数据绑定事件处理 完整事件处理示例

Public Sub SetupDataGridWithEvents()

' 绑定数据 dgv.DataSource = GetProducts()

' 添加事件处理 AddHandler dgv.DataBindingComplete, AddressOf dgv_DataBindingComplete AddHandler dgv.CellBeginEdit, AddressOf dgv_CellBeginEdit AddHandler dgv.CellEndEdit, AddressOf dgv_CellEndEdit AddHandler dgv.CellValueChanged, AddressOf dgv_CellValueChanged AddHandler dgv.RowEnter, AddressOf dgv_RowEnter AddHandler dgv.RowValidating, AddressOf dgv_RowValidating AddHandler dgv.Sorted, AddressOf dgv_Sorted End Sub

Private Sub dgv_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) ' 数据绑定完成后自动调整列宽 dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)

' 设置行号 For i As Integer = 0 To dgv.Rows.Count - 1 dgv.Rows(i).HeaderCell.Value = (i + 1).ToString() Next End Sub

Private Sub dgv_CellBeginEdit(sender As Object, e As DataGridViewCellCancelEventArgs) ' 记录编辑前的值 If e.RowIndex >= 0 AndAlso e.ColumnIndex >= 0 Then Dim oldValue = dgv.Rows(e.RowIndex).Cells(e.ColumnIndex).Value ' 可以保存到某个变量用于撤销操作 End If End Sub

Private Sub dgv_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) ' 验证编辑后的值 If dgv.Columns(e.ColumnIndex).Name = "Price" Then Dim newValue As Decimal If Not Decimal.TryParse(dgv.Rows(e.RowIndex).Cells(e.ColumnIndex).Value.ToString(), newValue) OrElse newValue < 0 Then dgv.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = 0 MessageBox.Show("价格必须是非负数字", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Warning) End If End If End Sub

Private Sub dgv_RowValidating(sender As Object, e As DataGridViewCellCancelEventArgs) ' 行级验证 Dim row As DataGridViewRow = dgv.Rows(e.RowIndex] If String.IsNullOrEmpty(row.Cells("Name").Value.ToString()) Then e.Cancel = True MessageBox.Show("产品名称不能为空", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning) End If End Sub

Private Sub dgv_Sorted(sender As Object, e As EventArgs) ' 排序后更新行号 For i As Integer = 0 To dgv.Rows.Count - 1 dgv.Rows(i).HeaderCell.Value = (i + 1).ToString() Next End Sub

以上涵盖了DataGridView的所有主要数据绑定方式,从简单的DataTable绑定到复杂的自定义绑定和虚拟模式绑定。

根据项目需求选择最适合的绑定方式,并考虑性能、可维护性和用户体验等因素。

相关文章