搜索时如何保持CheckedListBox项的选中状态?
解决CheckedListBox搜索时选中状态丢失的问题
问题根源在于使用DataView.RowFilter过滤数据时,CheckedListBox的项会重新渲染,原有的选中状态是基于项的索引绑定的,过滤后项的索引发生变化,导致选中状态丢失。直接操作选中项集合时还可能因为数据源变更引发异常,正确的做法是通过唯一标识(Property_Id)保存和恢复选中状态,具体实现如下:
- 定义集合存储选中项的唯一ID
在UserControl类中添加私有字段,用来持久化选中项的Property_Id:
private HashSet<int> _selectedPropertyIds = new HashSet<int>();
- 修改搜索文本变更事件,先保存选中ID再过滤,最后恢复选中状态
更新Searchtext_TextChanged方法,在过滤前把当前选中项的Property_Id存入集合,过滤完成后遍历新的项集合,根据ID匹配恢复选中:
private void Searchtext_TextChanged(object sender, EventArgs e) { if (checkedListBox1.DataSource is DataTable dt) { // 保存当前选中的Property_Id _selectedPropertyIds.Clear(); foreach (int index in checkedListBox1.CheckedIndices) { if (checkedListBox1.Items[index] is DataRowView rowView) { int propertyId = Convert.ToInt32(rowView["Property_Id"]); _selectedPropertyIds.Add(propertyId); } } // 执行过滤逻辑 var str = Searchtext.Text.Trim(); dt.DefaultView.RowFilter = string.IsNullOrEmpty(str) ? null : $"Property_Name LIKE '%{str}%'"; // 根据保存的ID恢复选中状态 foreach (int index in Enumerable.Range(0, checkedListBox1.Items.Count)) { if (checkedListBox1.Items[index] is DataRowView rowView) { int propertyId = Convert.ToInt32(rowView["Property_Id"]); checkedListBox1.SetItemChecked(index, _selectedPropertyIds.Contains(propertyId)); } } } }
- 可选:初始化加载时保留选中状态
如果需要在控件初始化或重新加载数据后恢复之前的选中状态,可在LoadProperty方法末尾添加恢复逻辑:
private void LoadProperty() { checkedListBox1.DisplayMember = "Property_Name"; checkedListBox1.ValueMember = "Property_Id"; checkedListBox1.DataSource = GetDataTable(); // 恢复之前保存的选中状态 foreach (int index in Enumerable.Range(0, checkedListBox1.Items.Count)) { if (checkedListBox1.Items[index] is DataRowView rowView) { int propertyId = Convert.ToInt32(rowView["Property_Id"]); checkedListBox1.SetItemChecked(index, _selectedPropertyIds.Contains(propertyId)); } } }
通过以上修改,无论搜索过滤如何改变项的显示集合,都能通过唯一的Property_Id准确恢复用户之前的选中状态,避免索引变化导致的状态丢失和异常问题。
内容的提问来源于stack exchange,提问作者WM1
相关产品推荐
相关产品推荐

