Класс ObservableCollection

Последнее обновление: 04.01.2022

Кроме стандартных классов коллекций типа списков, очередей, словарей, стеков .NET также предоставляет специальный класс ObservableCollection<T>. В отличие от ранее рассмотренных коллекций данный класс определен в пространстве имен System.Collections.ObjectModel. По функциональности коллекция ObservableCollection похожа на список List за тем исключением, что позволяет известить внешние объекты о том, что коллекция была изменена.

Создание и инициализация ObservableCollection

Для создания объекта класс 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

Среди методов класса 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
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850