【问题标题】:Collection that supports filtering, sorting, eding, adding and deleting items with notification支持过滤、排序、编辑、添加和删除带有通知的项目的集合
【发布时间】:2012-03-16 08:22:22
【问题描述】:

Silverlight、WPF 和 Windows Phone 是否支持某些集合,满足以下条件:

  1. 接受IEnumerable<T> 作为来源
  2. 允许过滤和排序项目
  3. 允许添加、编辑和删除过滤列表中的项目
  4. 对过滤/排序列表的任何更改也会反映到源列表(我认为过滤/排序列表仅作为源集合的视图)
  5. 对过滤/排序列表的任何更改都将反映在 UI 控件(Gridview、ListView...)上。

【问题讨论】:

    标签: wpf silverlight windows-phone-7 mvvm


    【解决方案1】:

    你想要一个 ObservableCollection。真的没有别的了。

    变体是您自己的实现 IList 的对象,但在内部执行您想要的任何操作。为此,您将创建一个如下所示的类

    class MyClass: IList, INotifyPropertyChanged
    {
      //implement it
    }
    

    编辑: 还有CollectionViewSource object

    【讨论】:

    • 其实 ObservableCollection 不会提供我所追求的。在这种特殊情况下,我知道通过网络检索的数据不能被其他任何人更改,所以我只想查询一次。这意味着当我过滤时,我正在创建一个新集合,然后我需要同步它们,过滤->原始。所以我需要像 CollectionView 这样具有可编辑功能的东西。
    【解决方案2】:

    最通用的集合是 ObservableCollection。您可以在构造函数中将 List 传递给它。通过 LINQ,您可以进行排序和过滤。您还可以使用 CollectionViewSource 在 XAML 中进行排序和筛选,但筛选是复杂的。并且个别项目需要实现iNotitifyPropertyChanged。我只知道WPF。

    如果您将过滤器隐藏在公共属性后面,您可以强制重新评估它。可能会把你带到你需要去的地方。

    public partial class MainWindow : Window
    {
        ObservableCollection<person> Persons = new ObservableCollection<person>();
    
        public MainWindow()
        {
            InitializeComponent();
    
            Persons.Add(new person("jim", 12));
            Persons.Add(new person("aa", 13));
            Persons.Add(new person("ff", 14));
            Persons.Add(new person("dd", 22));
            Persons.Add(new person("hky", 23));
            Persons.Add(new person("jsgdim", 24));
    
            List<person> YoungPersons = Persons.Where(per => per.Age < 20).ToList();
            Debug.WriteLine(Persons.Count.ToString());
            Debug.WriteLine(YoungPersons.Count.ToString());
            Debug.WriteLine(YoungPersonsProperty.Count.ToString());
            Persons[0].Name = "Jimmy";
            Debug.WriteLine(Persons[0].Name);
            Debug.WriteLine(YoungPersons[0].Name);
            Debug.WriteLine(YoungPersonsProperty[0].Name);
            Persons.Remove(Persons[0]);
            Debug.WriteLine(Persons.Count.ToString());
            Debug.WriteLine(YoungPersons.Count.ToString());
            Debug.WriteLine(YoungPersonsProperty.Count.ToString());
    
            string testName;
            DateTime startTime = DateTime.Now;        
            for (int i = 0; i < 1000000; i++)
            {
                testName = YoungPersonsProperty[0].Name;
            }
            DateTime endTime = DateTime.Now;
            TimeSpan ts = endTime - startTime;
            Debug.WriteLine(ts.Milliseconds.ToString());
        }
    
        public List<person> YoungPersonsProperty
        {
            get { return  Persons.Where(per => per.Age < 20).ToList(); } 
        }
    
        public class person : INotifyPropertyChanged
        {
            string name;
            int age;
            public event PropertyChangedEventHandler PropertyChanged;
            protected void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }
    
            public int Age { get { return age; } }
            public string Name 
            { 
                get { return name; }
                set 
                { 
                    name = value;
                    NotifyPropertyChanged("Name");
                }
            }
    
            public person (string Name, int Age) 
            {
                name = Name;
                age = Age;
            }
        }
    }
    

    我记得让 LINQ 过滤器动态应用而不将它们隐藏在属性后面,但我不记得如何。

    【讨论】:

    • 我已经这样做了,但是当我使用 linq 过滤时,我得到两个单独的列表,一个是原始的,一个是过滤的。如果我从过滤中删除一个项目,原始项目不会得到更新,所以我需要手动同步它们。请参阅我的第 4 点。
    • 是的,但这是非常低效的,每次删除/添加一个人时,您都会重新创建过滤集合。另一件事是控件将绑定到过滤列表,而不是列表,因此添加/删除记录将发生在过滤列表上,因此将与人员进行同步,而不是 YoungPersons 集合,这使得同步过程更加困难。
    • 效率极低??查看我运行的计时测试。在 723 毫秒内对 YoungPersonsProperty 进行了 100 万次调用,即每次调用需要 0.000723 毫秒。那是在 P4 桌面上。显然你不了解 Linq。至于同步,这很容易,但我已经帮您完成了。
    • 没有必要告诉我我不明白的东西,即使它是真的。低效并不意味着慢。想象一下,您需要在一个有 10 列的网格中重新加载数百条记录,仅添加/删除 1 条记录就浪费了内存和时间。更不用说在删除操作时您需要在重新加载之前保存一个记录指针,这样您就可以从您离开的地方回来。某事很容易做,并不一定意味着它是最好的方法。
    • 我也从来没有说过我不知道如何同步两个集合,我问是否有已经存在的解决方案。同样,如果您再次阅读我的帖子,您会发现您在实践中建议的方法是不可能的,因为您永远不会绑定到原始集合,而是绑定到过滤后,因此您需要同步原始集合,并且未过滤。
    猜你喜欢
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 2012-07-26
    • 2012-03-19
    • 2010-10-05
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多