VB.NET SQL Server下基于checkedlistbox选中项联动填充其他复选列表框咨询
实现方案(C# Winform,适配VS2017 + .NET Framework + SQL Server 2016)
前提假设
数据库存在两张关联表:
- 父部门表
Departments:字段DeptId(主键)、DeptName(父部门名称) - 子部门表
SubDepartments:字段SubDeptId(主键)、SubDeptName(子部门名称)、ParentDeptId(关联父部门DeptId)
步骤1:全局实体和变量定义
using System.Data.SqlClient; using System.Linq; // 父部门实体 public class DeptModel { public int DeptId { get; set; } public string DeptName { get; set; } } // 子部门实体 public class SubDeptModel { public int SubDeptId { get; set; } public string SubDeptName { get; set; } public int ParentDeptId { get; set; } } // 窗体类全局变量:存储父部门和对应子部门的映射,避免重复查询数据库 Dictionary<int, List<SubDeptModel>> deptToSubMap = new Dictionary<int, List<SubDeptModel>>();
步骤2:窗体加载时初始化父部门复选框checkedListBox1
private void Form1_Load(object sender, EventArgs e) { // 替换为自己的数据库连接字符串,建议实际项目存配置文件 string connStr = "Server=你的数据库地址;Database=你的库名;Uid=账号;Pwd=密码;"; // 1. 加载父部门到checkedListBox1 using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); SqlCommand cmd = new SqlCommand("SELECT DeptId, DeptName FROM Departments", conn); SqlDataReader dr = cmd.ExecuteReader(); List<DeptModel> deptList = new List<DeptModel>(); while (dr.Read()) { deptList.Add(new DeptModel { DeptId = Convert.ToInt32(dr["DeptId"]), DeptName = dr["DeptName"].ToString() }); } dr.Close(); checkedListBox1.DataSource = deptList; checkedListBox1.DisplayMember = "DeptName"; checkedListBox1.ValueMember = "DeptId"; } // 2. 预加载所有子部门到全局映射字典 using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); SqlCommand cmd = new SqlCommand("SELECT SubDeptId, SubDeptName, ParentDeptId FROM SubDepartments", conn); SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { int parentId = Convert.ToInt32(dr["ParentDeptId"]); SubDeptModel subDept = new SubDeptModel { SubDeptId = Convert.ToInt32(dr["SubDeptId"]), SubDeptName = dr["SubDeptName"].ToString(), ParentDeptId = parentId }; if (!deptToSubMap.ContainsKey(parentId)) deptToSubMap[parentId] = new List<SubDeptModel>(); deptToSubMap[parentId].Add(subDept); } } // 绑定勾选事件 checkedListBox1.ItemCheck += CheckedListBox1_ItemCheck; checkedListBox2.ItemCheck += CheckedListBox2_ItemCheck; }
步骤3:实现父部门勾选变化时同步checkedListBox2的逻辑
仅增删对应父部门的关联子部门,不清空全部内容:
private void CheckedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { DeptModel currentDept = (DeptModel)checkedListBox1.Items[e.Index]; int parentId = currentDept.DeptId; // 勾选父部门:添加对应子部门到checkedListBox2 if (e.NewValue == CheckState.Checked) { if (deptToSubMap.ContainsKey(parentId)) { foreach (var sub in deptToSubMap[parentId]) { // 避免重复添加 if (!checkedListBox2.Items.Cast<SubDeptModel>().Any(s => s.SubDeptId == sub.SubDeptId)) checkedListBox2.Items.Add(sub, false); // 默认子部门不勾选 } } } // 取消勾选父部门:仅移除对应子部门 else { if (deptToSubMap.ContainsKey(parentId)) { var toRemove = checkedListBox2.Items.Cast<SubDeptModel>() .Where(s => s.ParentDeptId == parentId).ToList(); foreach (var sub in toRemove) checkedListBox2.Items.Remove(sub); } } }
步骤4:实现子部门勾选变化时同步checkedListBox3的逻辑
仅加载checkedListBox2中已勾选的子部门:
private void CheckedListBox2_ItemCheck(object sender, ItemCheckEventArgs e) { SubDeptModel currentSub = (SubDeptModel)checkedListBox2.Items[e.Index]; // 勾选子部门:添加到checkedListBox3 if (e.NewValue == CheckState.Checked) { if (!checkedListBox3.Items.Cast<string>().Any(s => s == currentSub.SubDeptName)) checkedListBox3.Items.Add(currentSub.SubDeptName); // 若需要存储子部门ID,可改为添加SubDeptModel实体,设置DisplayMember即可 } // 取消勾选子部门:从checkedListBox3移除 else { var toRemove = checkedListBox3.Items.Cast<string>() .FirstOrDefault(s => s == currentSub.SubDeptName); if (toRemove != null) checkedListBox3.Items.Remove(toRemove); } }
注意事项
checkedListBox2、checkedListBox3不要绑定DataSource,直接操作Items集合才能实现动态增删- 子部门有重名场景下,建议
checkedListBox3也绑定SubDeptModel实体,通过ID判断避免误删
内容的提问来源于stack exchange,提问作者gurpreet
相关产品推荐
相关产品推荐

