Clasa ObservableCollection
Pe lângă clasele de colecții standard, cum ar fi listele, cozile, dicționarele și stivele, .NET oferă și o clasă specială numită ObservableCollection<T>. Spre deosebire de colecțiile discutate anterior, această clasă este definită în spațiul de nume System.Collections.ObjectModel.
Funcționalitatea colecției ObservableCollection este similară cu cea a listei List, cu excepția faptului că permite notificarea obiectelor externe atunci când colecția este modificată.
Crearea și inițializarea ObservableCollection
Pentru a crea un obiect, clasa ObservableCollection oferă mai mulți constructori. În primul rând, putem crea o colecție goală:
using System.Collections.ObjectModel;
ObservableCollection<string> people = new ObservableCollection<string>();
În acest caz, colecția people este tipizată cu tipul string, deci poate stoca doar șiruri de caractere.
O altă versiune a constructorului permite transmiterea în ObservableCollection a obiectelor dintr-o altă colecție sau array:
var people = new ObservableCollection<string>( new string[] {"Tom", "Bob", "Sam"});
Pentru inițializare, putem transmite valori printr-un inițializator între acolade:
var people = new ObservableCollection<string>
{
"Tom", "Bob", "Sam"
};
De asemenea, putem combina cele două metode anterioare:
var people = new ObservableCollection<string>( new string[] {"Mike", "Alice", "Kate" })
{
"Tom", "Bob", "Sam"
};
Accesarea elementelor colecției
Pentru a accesa elementele ObservableCollection, putem folosi indecși similar cu array-urile sau listele List:
var people = new ObservableCollection<string>
{
"Tom", "Bob", "Sam"
};
// obținem primul element
Console.WriteLine(people[0]); // Tom
// modificăm primul element
people[0] = "Tomas";
Console.WriteLine(people[0]); // Tomas
Parcurgerea colecției
Pentru a parcurge colecția, putem folosi cicluri standard:
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]);
}
Cu ajutorul proprietății Count, putem obține numărul de elemente din colecție.
Metodele ObservableCollection
Dintre metodele clasei ObservableCollection, menționăm următoarele:
- void Add(T item): adaugă un nou element în colecție
- void CopyTo(T[] array, int index): copiază în array elementele din colecție începând de la indexul specificat
- bool Contains(T item): returnează true dacă elementul item există în colecție
- void Clear(): șterge toate elementele din colecție
- int IndexOf(T item): returnează indexul primei apariții a elementului în colecție
- void Insert(int index, T item): inserează elementul item în colecție la indexulspecificat. Dacă nu există un astfel de index în colecție, se generează o excepție
- bool Remove(T item): șterge elementul item din colecție și returnează true dacă ștergerea a avut succes. Dacă în colecție există mai multe elemente identice, se șterge doar primul dintre ele
- void RemoveAt(int index): șterge elementul de la indexul specificat. Dacă nu există un astfel de index în colecție, se generează o excepție
- void Move(int oldIndex, int newIndex): mută elementul de la indexul oldIndex la poziția specificată de newIndex
Aplicarea metodelor:
using System.Collections.ObjectModel;
var people = new ObservableCollection<string>();
// adăugăm un element
people.Add("Bob");
// inserăm un element la indexul 0
people.Insert(0, "Tom");
// verificarea existenței elementului
bool bobExists = people.Contains("Bob"); // true
Console.WriteLine($"Bob exists: {bobExists}");
bool mikeExists = people.Contains("Mike"); // false
Console.WriteLine($"Mike exists: {mikeExists}");
// ștergerea unui element
people.Remove("Tom");
// ștergerea unui element de la indexul 0
people.RemoveAt(0);
Notificarea modificării colecției
Clasa ObservableCollection definește evenimentul CollectionChanged, la care ne putem abona pentru a gestiona orice modificări ale colecției. Acest eveniment este reprezentat de delegatul NotifyCollectionChangedEventHandler:
void NotifyCollectionChangedEventHandler(object? sender, NotifyCollectionChangedEventArgs e);
Al doilea parametru al delegatului - obiectul NotifyCollectionChangedEventArgs - stochează toate informațiile despre eveniment. În special, proprietatea sa Action permite aflarea naturii modificărilor. Aceasta stochează una dintre valorile din enumerarea NotifyCollectionChangedAction:
- NotifyCollectionChangedAction.Add: adăugare
- NotifyCollectionChangedAction.Remove: ștergere
- NotifyCollectionChangedAction.Replace: înlocuire
- NotifyCollectionChangedAction.Move: mutarea obiectului în cadrul colecției la o nouă poziție
- NotifyCollectionChangedAction.Reset: resetarea conținutului colecției (de exemplu, la ștergerea colecției cu metoda Clear())
În plus, proprietățile NewItems și OldItems permit obținerea respectiv a obiectelor adăugate și șterse. Astfel, avem control deplin asupra gestionării adăugării, ștergerii și înlocuirii obiectelor din colecție.
Să presupunem că avem următoarea clasă Person, care reprezintă un utilizator:
class Person
{
public string Name { get; }
public Person(string name) => Name = name;
}
Pentru a gestiona colecția de obiecte Person, definim următorul program:
using System.Collections.ObjectModel;
using System.Collections.Specialized;
var people = new ObservableCollection<Person>()
{
new Person("Tom"),
new Person("Sam")
};
// ne abonăm la evenimentul de modificare a colecției
people.CollectionChanged += People_CollectionChanged;
people.Add(new Person("Bob")); // adăugăm un nou element
people.RemoveAt(1); // ștergem un element
people[0] = new Person("Eugene"); // înlocuim un element
Console.WriteLine("\nLista utilizatorilor:");
foreach (var person in people)
{
Console.WriteLine(person.Name);
}
// handler pentru modificarea colecției
void People_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add: // dacă este adăugare
if(e.NewItems?[0] is Person newPerson)
Console.WriteLine($"Adăugat obiect nou: {newPerson.Name}");
break;
case NotifyCollectionChangedAction.Remove: // dacă este ștergere
if (e.OldItems?[0] is Person oldPerson)
Console.WriteLine($"Șters obiect: {oldPerson.Name}");
break;
case NotifyCollectionChangedAction.Replace: // dacă este înlocuire
if ((e.NewItems?[0] is Person replacingPerson) &&
(e.OldItems?[0] is Person replacedPerson))
Console.WriteLine($"Obiectul {replacedPerson.Name} a fost înlocuit cu obiectul {replacingPerson.Name}");
break;
}
}
Aici, metoda People_CollectionChanged acționează ca un handler pentru modificările colecției, iar cu ajutorul parametrului NotifyCollectionChangedEventArgs obținem informații despre modificare.
Rezultatul în consolă al programului:
Adăugat obiect nou: Bob
Șters obiect: Sam
Obiectul Tom a fost înlocuit cu obiectul Eugene
Lista utilizatorilor:
Eugene
Bob