使用Linq通过文本框过滤ListBox时列表项未发生变化如何解决
问题产生原因
- TextChanged事件中每次调用
GetList时传入的是新创建的空List<SemesterDetails>对象,没有传入存储了所有模块数据的原始集合,Linq过滤空集合后没有可添加到ListBox的有效数据。 GetList方法执行时没有先清空ListBox的原有项,就算后续传入了有效数据,也只会在原有项基础上累加,不会覆盖旧的未过滤内容。- 未在窗体层面持久化存储全量的原始模块数据,每次过滤时没有可用于筛选的基准数据源。
修复步骤
- 首先在窗体类中定义全局变量存储全量模块数据,在首次加载模块数据时为该变量赋值:
// 窗体类的全局成员,存储所有未过滤的原始模块数据 private List<SemesterDetails> _allModules = new List<SemesterDetails>(); // 你首次加载模块数据的位置(如窗体构造函数、数据初始化方法)调用该方法赋值 public void InitModules(List<SemesterDetails> allModules) { _allModules = allModules; // 首次加载时展示全部数据 GetList(_allModules); }
- 修改
GetList方法,增加清空原有项的逻辑,同时适配空过滤关键词的场景:
public void GetList(List<SemesterDetails> modules) { // 先清空原有项,避免新旧内容叠加 LstModules.Items.Clear(); string filter = txtFilter.Text?.Trim() ?? string.Empty; // 过滤关键词为空时返回全部数据,否则按模块名过滤 var filteredItems = string.IsNullOrEmpty(filter) ? modules : modules.Where(m => m.ModuleName.Contains(filter)); foreach (var item in filteredItems) { LstModules.Items.Add(item); } }
- 修改
TextChanged事件的逻辑,传入全局存储的全量数据:
private void txtFilter_TextChanged(object sender, TextChangedEventArgs e) { // 直接传入全量原始数据进行过滤 GetList(_allModules); }
可选优化
如果需要实现不区分大小写的过滤,可以将过滤逻辑修改为:
modules.Where(m => m.ModuleName.Contains(filter, StringComparison.OrdinalIgnoreCase))
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

