12.3 可观察的集合

如果需要集合中的元素何时删除或添加的信息,就可以使用ObservableCollection<T>类。这个类最初是为WPF定义的,这样UI就可以得知集合的变化,Windows应用程序使用它的方式相同。在.NET Core中,需要引用NuGet包System.ObjectModel。这个类的名称空间是System.Collections. ObjectModel。

ObservableCollection<T>类派生自Collection<T>基类,该基类可用于创建自定义集合,并在内部使用List<T>类。重写基类中的虚方法SetItem()和RemoveItem(),以触发CollectionChanged事件。这个类的用户可以使用INotifyCollectionChanged接口注册这个事件。

下面的示例说明了ObservableCollection<string>()方法的用法,其中给CollectionChanged事件注册了Data_CollectionChanged()方法。把两项添加到末尾,再插入一项,并删除一项(代码文件ObservableCollectionSample/Program.cs):

        var data = new ObservableCollection<string>();
        data.CollectionChanged += Data_CollectionChanged;
        data.Add("One");
        data.Add("Two");
        data.Insert(1, "Three");
        data.Remove("One");

ObservableCollectionSample使用如下依赖项和名称空间:

依赖项:

        NETStandard.Library
        System.ObjectModel

名称空间:

        System.Collections.ObjectModel
        System.Collections.Specialized
        static System.Console

Data_CollectionChanged()方法接收NotifyCollectionChangedEventArgs,其中包含了集合的变化信息。Action属性给出了是否添加或删除一项的信息。对于删除的项,会设置OldItems属性,列出删除的项。对于添加的项,则设置NewItems属性,列出新增的项。

        public static void Data_CollectionChanged(object sender,
                                              NotifyCollectionChangedEventArgs e)
        {
          WriteLine($"action: {e.Action.ToString()}");
          if (e.OldItems ! = null)
          {
            WriteLine($"starting index for old item(s): {e.OldStartingIndex}");
            WriteLine("old item(s):");
            foreach (var item in e.OldItems)
            {
              WriteLine(item);
            }
          }
          if (e.NewItems ! = null)
          {
            WriteLine($"starting index for new item(s): {e.NewStartingIndex}");
            WriteLine("new item(s): ");
            foreach (var item in e.NewItems)
            {
              WriteLine(item);
            }
          }
          WriteLine();
        }

运行应用程序,输出如下所示。先在集合中添加One和Two项,显示的Add动作的索引是0和1。第3项Three插入在位置1上,所以显示的Add动作的索引是1。最后删除One项,显示的Remove动作的索引是0:

        action: Add
        starting index for new item(s): 0
        new item(s):
        One
        action: Add
        starting index for new item(s): 1
        new item(s):
        Two
        action: Add
        starting index for new item(s): 1
        new item(s):
        Three
        action: Remove
        starting index for old item(s): 0
        old item(s):
        One