如何筛选Observable Collection中属性匹配指定条件的项?—— Hymn集合按HymnType Title筛选后返回Null问题排查
问题原因与解决方案
你的筛选后列表返回Null的核心问题在于LINQ的Where方法返回的是IEnumerable<Hymn>类型,而非ObservableCollection<Hymn>。当你用as ObservableCollection<Hymn>进行类型转换时,因为两种类型不兼容,转换失败,结果就变成了Null——这就是问题的根源。
解决方法1:将筛选结果重新包装为ObservableCollection
直接把Where返回的IEnumerable<Hymn>传入ObservableCollection的构造函数,创建一个新的集合实例:
public class HymnTypeContentPageViewModel : BaseViewModel { ObservableCollection<Hymn> _hymns; public ObservableCollection<Hymn> Hymns { get => _hymns; set => SetProperty(ref _hymns, value); } public HymnTypeContentPageViewModel(HymnType hymnType) { string keyword = hymnType.Title.ToLower(); // 先初始化原始集合 var initialHymns = new ObservableCollection<Hymn> { new Hymn { HymnNumber = 201, Title = "All Things Bright and Beautiful", HymnTypeName = StaticStrings.AncientAndModern, Body = "Test Body Ancient and Modern" }, new Hymn { HymnNumber = 270, Title = "He Arose", HymnTypeName = StaticStrings.SomeOtherHymns, Body = "Test Body Some Other Hymn" }, }; // 将筛选后的IEnumerable转为ObservableCollection Hymns = new ObservableCollection<Hymn>(initialHymns.Where(h => h.HymnTypeName.ToLower().Contains(keyword))); } }
解决方法2:保留原集合引用(适合绑定场景)
如果你的UI已经绑定了Hymns集合,不想重新创建实例,可以先清空原集合,再添加筛选后的项:
public class HymnTypeContentPageViewModel : BaseViewModel { ObservableCollection<Hymn> _hymns; public ObservableCollection<Hymn> Hymns { get => _hymns; set => SetProperty(ref _hymns, value); } public HymnTypeContentPageViewModel(HymnType hymnType) { string keyword = hymnType.Title.ToLower(); Hymns = new ObservableCollection<Hymn> { new Hymn { HymnNumber = 201, Title = "All Things Bright and Beautiful", HymnTypeName = StaticStrings.AncientAndModern, Body = "Test Body Ancient and Modern" }, new Hymn { HymnNumber = 270, Title = "He Arose", HymnTypeName = StaticStrings.SomeOtherHymns, Body = "Test Body Some Other Hymn" }, }; // 先获取筛选结果,再更新原集合 var filteredHymns = Hymns.Where(h => h.HymnTypeName.ToLower().Contains(keyword)).ToList(); Hymns.Clear(); foreach (var hymn in filteredHymns) { Hymns.Add(hymn); } } }
优化建议:避免不必要的ToLower调用
为了提高效率并避免文化差异带来的问题,可以用StringComparison.OrdinalIgnoreCase替代ToLower()进行不区分大小写的匹配:
// 替代ToLower的写法 Hymns = new ObservableCollection<Hymn>(initialHymns.Where(h => h.HymnTypeName.Contains(keyword, StringComparison.OrdinalIgnoreCase)));
内容的提问来源于stack exchange,提问作者Orukele
相关产品推荐
相关产品推荐

