VB.NET WinForms中DataGridViewComboBox基于另一ComboBox筛选实现
解决方案
思路1:直接筛选当前行ComboBox的数据源
你已经能获取到目标行的DataGridViewComboBoxCell,可以通过DataView筛选实现联动,具体步骤如下:
- 确保企业数据源(比如
DataTable dtAllEnterprises)包含ProductID、EnterpriseID、EnterpriseName字段,用于关联产品与对应生产企业。 - 在产品ComboBox的变更事件中,完成筛选与绑定:
Private Sub dgvProducts_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles MyDataGridView.EditingControlShowing ' 判断当前编辑的是产品列 If MyDataGridView.CurrentCell.ColumnIndex = ProductColIndex Then Dim productCbo As ComboBox = TryCast(e.Control, ComboBox) If productCbo IsNot Nothing Then ' 移除旧绑定避免重复触发事件 RemoveHandler productCbo.SelectedIndexChanged, AddressOf ProductCbo_SelectedIndexChanged AddHandler productCbo.SelectedIndexChanged, AddressOf ProductCbo_SelectedIndexChanged End If End If End Sub Private Sub ProductCbo_SelectedIndexChanged(sender As Object, e As EventArgs) Dim productCbo As ComboBox = TryCast(sender, ComboBox) If productCbo Is Nothing Then Return Dim currentRowIndex As Integer = MyDataGridView.CurrentCell.RowIndex Dim currentRow As DataGridViewRow = MyDataGridView.Rows(currentRowIndex) If currentRow.IsNewRow Then Return ' 新增行未确认时可跳过或按需处理 ' 获取选中产品的ID(假设产品数据源的ValueMember为ProductID) Dim selectedProductID As Integer = CInt(productCbo.SelectedValue) ' 获取当前行的企业ComboBox单元格 Dim enterpriseCboCell As DataGridViewComboBoxCell = TryCast(currentRow.Cells(EnterpriseColIndex), DataGridViewComboBoxCell) If enterpriseCboCell Is Nothing Then Return ' 用DataView过滤出可生产该产品的企业 Dim filteredEnterprises As New DataView(dtAllEnterprises) filteredEnterprises.RowFilter = $"ProductID = {selectedProductID}" ' 重新绑定当前行的企业ComboBox enterpriseCboCell.DataSource = filteredEnterprises enterpriseCboCell.ValueMember = "EnterpriseID" enterpriseCboCell.DisplayMember = "EnterpriseName" ' 可选:清空当前企业选择,避免显示无效选项 enterpriseCboCell.Value = DBNull.Value End Sub
如果企业数据源是BindingSource,也可以直接设置BindingSource.Filter属性后再赋值给单元格的DataSource。
思路2:参数化SQL查询获取对应企业
适合企业数据量大、不想在客户端存储全量数据的场景,实现步骤如下:
- 编写带参数的SQL查询语句:
SELECT EnterpriseID, EnterpriseName FROM Enterprises WHERE ProductID = @ProductID
- 在产品ComboBox变更事件中执行参数化查询并绑定:
Private Sub ProductCbo_SelectedIndexChanged(sender As Object, e As EventArgs) Dim productCbo As ComboBox = TryCast(sender, ComboBox) If productCbo Is Nothing Then Return Dim currentRowIndex As Integer = MyDataGridView.CurrentCell.RowIndex Dim currentRow As DataGridViewRow = MyDataGridView.Rows(currentRowIndex) If currentRow.IsNewRow Then Return Dim selectedProductID As Integer = CInt(productCbo.SelectedValue) Dim enterpriseCboCell As DataGridViewComboBoxCell = TryCast(currentRow.Cells(EnterpriseColIndex), DataGridViewComboBoxCell) If enterpriseCboCell Is Nothing Then Return ' 执行参数化查询获取对应企业 Using conn As New SqlConnection("你的数据库连接字符串") Dim sql As String = "SELECT EnterpriseID, EnterpriseName FROM Enterprises WHERE ProductID = @ProductID" Using cmd As New SqlCommand(sql, conn) cmd.Parameters.AddWithValue("@ProductID", selectedProductID) conn.Open() Dim dtFiltered As New DataTable() dtFiltered.Load(cmd.ExecuteReader()) conn.Close() ' 绑定到当前行的企业ComboBox enterpriseCboCell.DataSource = dtFiltered enterpriseCboCell.ValueMember = "EnterpriseID" enterpriseCboCell.DisplayMember = "EnterpriseName" enterpriseCboCell.Value = DBNull.Value End Using End Using End Sub
额外注意事项
- 新增行处理:如果允许用户直接新增行,可根据需求调整
IsNewRow的判断逻辑,决定是否在新增行未保存时就触发筛选。 - 事件重复绑定:在
EditingControlShowing中必须先移除旧事件绑定再添加新的,避免多次触发SelectedIndexChanged。 - 数据类型匹配:确保
ProductID、EnterpriseID的类型与数据源/数据库中的类型一致,避免转换错误。
内容的提问来源于stack exchange,提问作者kpg
相关产品推荐
相关产品推荐

