C# 过滤对象C的可观察集合#

C# 过滤对象C的可观察集合#,c#,xamarin,xamarin.forms,C#,Xamarin,Xamarin.forms,我想为我的Xamarin表单应用程序按名称筛选Person对象的ObservableCollection。 我们的目标是过滤这个observeableCollection,只显示其中的一部分 这是我的Person对象类: public class Person { public string Name { get; set; } public string Address { get; set; } public string Phone { get; set; } }

我想为我的Xamarin表单应用程序按名称筛选
Person
对象的
ObservableCollection
。 我们的目标是过滤这个
observeableCollection
,只显示其中的一部分

这是我的Person对象类:

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string Phone { get; set; }
}
我试着做一个这样的过滤器:

private ObservableCollection<Person> personItems = new ObservableCollection<Person>();

public ObservableCollection<Person> PersonItems
{
    get { return personItems; }
    set { personItems = value; OnPropertyChanged(); }
}

public void FilterPerson(string filter)
{
    if (string.IsNullOrWhiteSpace(filter))
    {
        PersonItems = personItems;
    }
    else 
    {
        PersonItems = personItems.Where((person) => person. Name.ToLower().Contains(filter));
        // Error here
    }
}
private ObservableCollection personItems=new ObservableCollection();
公众可观察收集个人信息
{
获取{return personItems;}
设置{personItems=value;OnPropertyChanged();}
}
公共空过滤器person(字符串过滤器)
{
if(string.IsNullOrWhiteSpace(filter))
{
PersonItems=PersonItems;
}
其他的
{
PersonItems=PersonItems.Where((person)=>person.Name.ToLower().Contains(filter));
//这里出错
}
}
我有一个错误:

无法显式转换类型: “System.Collections.Generic.IEnumerable”到 'System.Collections.ObjectModel.ObservableCollection


基本上有两种解决方案:

  • 如果PersonsItems列表不是很大,那么每次新的筛选器字符串到达时,您都可以重新创建整个集合。在这种情况下,您甚至不需要ObservableCollection(因为您不更改集合本身,而是更改对集合的引用)。在这种情况下,将重新创建所有UI元素

    PersonItems = originalItems.Where((person) => person. Name.ToLower().Contains(filter)).ToList();
    
  • 如果您的PersonsItems列表足够大,则第一个解决方案不是一个选项。在这种情况下,您需要对应该添加/删除的对象手动调用Add/Remove方法。ObservableCollection有一个命令式API,它在每次调用Add/Remove时都会触发一个事件。反过来,ItemsControl可以观察到该事件,该控件将进行相应的UI更改。Linq有一个声明式API。这就是为什么你需要手动同步一个列表来显示一个过滤过的列表


  • 为了做到这一点,我在过去使用了James Montemagno的ObserverAgeCollection和Grouping helper函数。你可以在这个插件中找到它们

    是数不清的

    将其替换为
    PersonItems=newobservedcollection(PersonItems.Where((person)=>person.Name.ToLower().Contains(filter))


    您必须使用过滤结果重新创建可观察的集合。

    可观察的集合是可观察的。您应该删除不需要的项目,而不是用新集合替换整个集合。可能的重复项也很可能缺少代码“personItems=”,否则错误不会出现。请尝试使用CollectinViewSourceThank@mikus复制粘贴代码时忘记了,正如上面建议的那样,您还可以使用支持筛选的CollectionView。好的,谢谢您的解释,但是第一个解决方案不起作用,原因是否相同?正如我所写的,对于第一种方法,您不需要ObservableCollection。只需将PersonItems属性/支持字段类型更改为List并使用上述赋值即可。我使用此插件的好主意完全超出了使用ObservableCollection的全部目的,即在事情发生变化时从中获取事件,以便UI能够对准确的变化集作出反应。@Matti Virkkunen愿意分享您对这些变化的见解吗替代方法,而不仅仅是否决接受的答案?您永远不必重新创建您的可观察集合有时更新可观察集合的成本太高(大量项目绑定到UI,UI闪烁和/或变得无响应),而重新创建是正确的方法。此外,noone还提供了一种更好的过滤ObservableCollection的方法(除了恢复使用ICollectionView之外)
    PersonItems = personItems.Where((person) => person. Name.ToLower().Contains(filter));