You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForm的DataGridView重复添加CheckBox列问题求助

问题原因

每次ComboBox的SelectedIndexChanged事件触发都会调用一次GetRecords方法,你将CheckBox列插入、全选CheckBox控件添加、点击事件绑定的逻辑都写在了这个方法里,方法每执行一次就会新增1个CheckBox列、重复绑定多次相同事件,调用多少次就会出现多少个重复列。

解决方法

  • 将列初始化、控件添加、事件绑定的逻辑拆分到窗体加载事件中,全局只执行一次
  • 调整数据绑定逻辑,避免重复生成列
  • 原代码使用字符串拼接SQL存在注入风险,建议替换为参数化查询

修正后代码示例

窗体加载事件逻辑

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    ' 全局仅初始化一次
    DataGridView1.AutoGenerateColumns = False

    ' 添加CheckBox列
    Dim checkBoxColumn As DataGridViewCheckBoxColumn = New DataGridViewCheckBoxColumn()
    checkBoxColumn.HeaderText = ""
    checkBoxColumn.Width = 30
    checkBoxColumn.Name = "checkBoxColumn"
    DataGridView1.Columns.Insert(0, checkBoxColumn)

    ' 添加表头全选CheckBox
    Dim headerCellLocation As Point = Me.DataGridView1.GetCellDisplayRectangle(0, -1, True).Location
    headerCheckBox.Location = New Point(headerCellLocation.X + 8, headerCellLocation.Y + 2)
    headerCheckBox.BackColor = Color.White
    headerCheckBox.Size = New Size(18, 18)
    DataGridView1.Controls.Add(headerCheckBox)

    ' 绑定事件,仅绑定一次
    AddHandler headerCheckBox.Click, AddressOf HeaderCheckBox_Clicked
    AddHandler DataGridView1.CellContentClick, AddressOf DataGridView_CellClick
End Sub

调整后的GetRecords方法

Private Sub GetRecords()
    ' 仅保留数据查询和绑定逻辑
    Dim query As String = " select distinct t.CPTCode,t.ServiceName,t.DepartmentName,t.SubName,t.Name as Company,t.bedcatename,t.ServiceCharge " &
                          " from tariffpsri t " &
                          " inner join psrirate p on t.Validid= p.Validid " &
                          " inner join ItemOfService i on t.ServiceId = i.ServiceId " &
                          " where t.DepartmentName= @DeptName " &
                          " And t.companyid = 1 And i.Active = 1 " &
                          " And Convert(varchar, p.ValidFrom, 111) = @ValidFrom " &
                          " order by CPTCode "

    conn = GetConnect()
    conn.Open()
    Using cmd As SqlCommand = New SqlCommand(query, conn)
        cmd.CommandType = CommandType.Text
        ' 使用参数化查询避免SQL注入
        cmd.Parameters.AddWithValue("@DeptName", ComboBox2.Text)
        cmd.Parameters.AddWithValue("@ValidFrom", ComboBox1.Text)
        Using sda As SqlDataAdapter = New SqlDataAdapter(cmd)
            Using dt As DataTable = New DataTable()
                sda.Fill(dt)
                ' 绑定前清空原有数据
                DataGridView1.DataSource = Nothing
                DataGridView1.DataSource = dt
            End Using
        End Using
    End Using
    conn.Close()
End Sub

可选适配逻辑

如果你没有在设计器提前配置业务列,需要自动生成查询字段对应的列,可以在绑定数据源前添加以下逻辑:

' 保留第一列CheckBox,清空旧的业务列
While DataGridView1.Columns.Count > 1
    DataGridView1.Columns.RemoveAt(1)
End While
DataGridView1.AutoGenerateColumns = True

你原有的全选和单元格点击逻辑不需要修改,直接保留即可。


内容的提问来源于stack exchange,提问作者gurpreet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 10:48:03