Кроме стандартных классов коллекций типа списков, очередей, словарей, стеков .NET также предоставляет специальный класс ObservableCollection<T>. В отличие от ранее рассмотренных коллекций данный класс определен в пространстве имен System.Collections.ObjectModel. По функциональности коллекция ObservableCollection похожа на список List за тем исключением, что позволяет известить внешние объекты о том, что коллекция была изменена.
Для создания объекта класс ObservableCollection предоставляет ряд конструкторов. Прежде всего мы можем создать пустую коллекцию:
using System.Collections.ObjectModel; ObservableCollection<string> people = new ObservableCollection<string>();
В данном случае коллекция people типизируется типом string, поэтому может хранить только строки.
Другая версия конструктора позволяет передать в ObservableCollection объекты из другой коллекции или массива:
var people = new ObservableCollection<string>( new string[] {"Tom", "Bob", "Sam"});
Для инициализации можно через инициализатор в фигурных скобках передать значения
var people = new ObservableCollection<string> { "Tom", "Bob", "Sam" };
Также можно сочетать предыдущие два способа:
var people = new ObservableCollection<string>( new string[] {"Mike", "Alice", "Kate" }) { "Tom", "Bob", "Sam" };
Для обращения к элементам ObservableCollection можно применять индексы на манер массивов или списков List:
var people = new ObservableCollection<string> { "Tom", "Bob", "Sam" }; // получаем первый элемент Console.WriteLine(people[0]); // Tom // изменяем первый элемент people[0] = "Tomas"; Console.WriteLine(people[0]); // Tomas
Для перебора коллекции можно применять стандартные циклы:
using System.Collections.ObjectModel; var people = new ObservableCollection<string> { "Tom", "Bob", "Sam" }; foreach(var person in people) { Console.WriteLine(person); } for (int i =0; i < people.Count; i++) { Console.WriteLine(people[i]); }
С помощью свойства Count можно получить количество элементов в коллекции.
Среди методов класса ObservableCollection можно отметить следующие:
void Add(T item): добавление нового элемента в коллекцию
void CopyTo(T[] array, int index,): копирует в массив array элементы из коллекции начиная с индекса index
bool Contains(T item): возвращает true
, если элемент item есть в коллекции
void Clear(): удаляет из коллекции все элементы
int IndexOf(T item): возвращает индекс первого вхождения элемента в коллекции
void Insert(int index, T item): вставляет элемент item в коллекцию по индексу index. Если такого индекса в коллекции нет, то генерируется исключение
bool Remove(T item): удаляет элемент item из коллекции, и если удаление прошло успешно, то возвращает true. Если в коллекции несколько одинаковых элементов, то удаляется только первый из них
void RemoveAt(int index): удаление элемента по указанному индексу index. Если такого индекса в коллекции нет, то генерируется исключение
void Move(int oldIndex, int newIndex): перемещает элемент с индекса oldIndex на позицию по индексу newIndex
Применение методов:
using System.Collections.ObjectModel; var people = new ObservableCollection<string>(); // добавляем элемент people.Add("Bob"); // вставляем элемент по индексу 0 people.Insert(0, "Tom"); // проверка наличия элемента bool bobExists = people.Contains("Bob"); // true Console.WriteLine($"Bob exists: {bobExists}"); bool mikeExists = people.Contains("Mike"); // false Console.WriteLine($"Mike exists: {mikeExists}"); // удаляем элемент people.Remove("Tom"); // удаляем элемент по индексу 0 people.RemoveAt(0);
Класс ObservableCollection определяет событие CollectionChanged, подписавшись на которое, мы можем обработать любые изменения коллекции. Данное событие представляет делегат NotifyCollectionChangedEventHandler:
void NotifyCollectionChangedEventHandler(object? sender, NotifyCollectionChangedEventArgs e);
Второй параметр делегата - объект NotifyCollectionChangedEventArgs хранит всю информацию о событии. В частности, его
свойство Action
позволяет узнать характер изменений. Оно хранит одно из значений
из перечисления NotifyCollectionChangedAction:
NotifyCollectionChangedAction.Add
: добавление
NotifyCollectionChangedAction.Remove
: удаление
NotifyCollectionChangedAction.Replace
: замена
NotifyCollectionChangedAction.Move
: перемещение объекта внутри коллекции на новую позицию
NotifyCollectionChangedAction.Reset
: сброс содержимого коллекции (например, при ее очистке с помощью метода Clear()
)
Кроме того, свойства NewItems
и OldItems
позволяют получить соответственно добавленные и удаленные объекты. Таким образом, мы получаем полный
контроль над обработкой добавления, удаления и замены объектов в коллекции.
Допустим, у нас будет следующий класс Person, который представляет пользователя:
class Person { public string Name { get; } public Person(string name) => Name = name; }
Для управления коллекцией объектов Person определим следующую программу:
using System.Collections.ObjectModel; using System.Collections.Specialized; var people = new ObservableCollection<Person>() { new Person("Tom"), new Person("Sam") }; // подписываемся на событие изменения коллекции people.CollectionChanged += People_CollectionChanged; people.Add(new Person("Bob")); // добавляем новый элемент people.RemoveAt(1); // удаляем элемент people[0] = new Person("Eugene"); // заменяем элемент Console.WriteLine("\nСписок пользователей:"); foreach (var person in people) { Console.WriteLine(person.Name); } // обработчик изменения коллекции void People_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: // если добавление if(e.NewItems?[0] is Person newPerson) Console.WriteLine($"Добавлен новый объект: {newPerson.Name}"); break; case NotifyCollectionChangedAction.Remove: // если удаление if (e.OldItems?[0] is Person oldPerson) Console.WriteLine($"Удален объект: {oldPerson.Name}"); break; case NotifyCollectionChangedAction.Replace: // если замена if ((e.NewItems?[0] is Person replacingPerson) && (e.OldItems?[0] is Person replacedPerson)) Console.WriteLine($"Объект {replacedPerson.Name} заменен объектом {replacingPerson.Name}"); break; } }
Здесь в качестве обработчика изменений коллекции выступает метод People_CollectionChanged
, в котором с помощью параметра NotifyCollectionChangedEventArgs
получаем информацию об изменении. Консольный вывод программы:
Добавлен новый объект: Bob Удален объект: Sam Объект Tom заменен объектом Eugene Список пользователей: Eugene Bob