VB.NET 如何根据ListView1勾选项从数据库正确填充ListView2
问题根因
- 触发事件选择错误:你当前用
MouseUp监听ListView1操作,只要鼠标在控件内抬起就会触发填充逻辑,不管是勾选、取消勾选、还是点击空白/列头都会执行函数,不符合仅勾选触发的需求。 - 函数逻辑缺陷:
- 遍历勾选项时多余执行
ListView1.Items(i).Selected = True,会强制选中所有ListView1项,属于无用逻辑 - 仅在存在勾选项(Yn=True)时操作ListView2,没有补充所有项都取消勾选时清空ListView2的逻辑
- 操作ListView2时多余执行
ListView3.Clear(),会误清空无关控件内容
- 遍历勾选项时多余执行
修复后代码
Private Function selectionfromDeptTofillLv2() As Boolean Dim i As Integer, Yn As Boolean Yn = False Dim strDept As String = "" ' 移除多余的选中所有项逻辑 For i = 0 To ListView1.Items.Count - 1 If ListView1.Items(i).Checked = True Then If Trim(strDept) <> "" Then strDept = strDept & "," strDept = strDept & Trim(ListView1.Items(i).Tag) Yn = True End If Next conn = GetConnect() conn.Open() If Yn = True Then Dim strSQL As String = "", strSQLdept As String = "" strSQL = "select SubName,SubDeptID from DepartmentSub where active=1" If Trim(strDept) <> "" Then strSQLdept = strSQLdept & " And DepartmentID In (" & strDept & ")" & " order by SubName" strSQL = strSQL & strSQLdept Dim cmd3 As SqlCommand = New SqlCommand(strSQL, conn) Dim sda3 As SqlDataAdapter = New SqlDataAdapter(cmd3) Dim dt3 As DataTable = New DataTable() sda3.Fill(dt3) With ListView2 ' 移除多余的ListView3清空逻辑 .Clear() .View = View.Details .GridLines = True .Columns.Clear() .Items.Clear() .Columns.Add(" ", 30) .Columns.Add("Sub Department Name", 250, HorizontalAlignment.Left) For Each row As DataRow In dt3.Rows Dim item As ListViewItem = New ListViewItem item.SubItems.Add(row("SubName").ToString()) item.Tag = Val(row("SubDeptID").ToString) item.Checked = False .Items.Add(item) Next End With Else ' 无勾选项时清空ListView2 ListView2.Clear() End If conn.Close() Return Yn End Function ' 全选按钮逻辑 Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.Click For Each lvitem As ListViewItem In Me.ListView1.Items lvitem.Checked = CheckBox2.Checked Next ' 全选时触发刷新,取消全选直接清空ListView2 If CheckBox2.Checked Then selectionfromDeptTofillLv2() Else ListView2.Clear() End If End Sub ' 替换原来的MouseUp事件,仅勾选状态变更时触发 Private Sub ListView1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles ListView1.ItemCheck ' 仅勾选操作触发刷新,取消勾选不触发,符合需求 If e.NewValue = CheckState.Checked Then ' 延迟执行,等项的勾选状态更新完成后再调用函数 Me.BeginInvoke(Sub() selectionfromDeptTofillLv2()) End If End Sub
补充注意事项
- 当前代码直接拼接SQL语句存在SQL注入风险,建议改为参数化查询实现IN条件的传值
- 如果需求是取消勾选时也同步刷新ListView2(移除对应部门的子项),只需要删除
ItemCheck事件里的If e.NewValue = CheckState.Checked判断即可。
内容的提问来源于stack exchange,提问作者gurpreet
相关产品推荐
相关产品推荐

