Publikoval Michal Kočí dňa 22.2.2005 o 22:11 v kategórii .Net
Tým, že sme sa zaviazali implementovať rozhranie IBindingList, zaviazali sme sa aj poskytnúť udalosť ListChanged. Tá signalizuje, že sa s kolekciou dát čosi udialo (napríklad, že bol do nej pridaný nový prvok). Aby sme si vyvolanie udalosti uľahčili (a spravili transparentným), pripravíme si aj metódu, ktorá ak máme odberateľov udalosti, tak udalosť oznámi. To bude vykonávať metóda OnListChanged.
public event ListChangedEventHandler ListChanged; protected virtual void OnListChanged(ListChangedEventArgs ev) { if (ListChanged != null) { ListChanged(this, ev); } }
Teraz sa vrátim k mojej informácii, že udalosti budeme používať na synchronizovanie originálnej a sortovanej kolekcie. Spomeňte si, že napríklad pri pridávaní nového prvku sme pridanie prvku uzavreli medzi dvojicu met´do, ktoré mali na starosti vyvolanie udalosti: OnInsert a OnInsertComplete. No a na synchronizáciu použijeme práve vždy tú druhú z dvojice metód (tú so suffixom Complete). V tej vždy (pridanie, odstránenie, zmena prvku, ...) skontrolujeme či máme kolekciu sortovanú (isSorted je true) a ak áno, potom vykonáme príslušnú akciu (pridanie, odstránenie prvku, ...) nad originálnou nezoradenou kolekciou. Tým dosiahneme efektu, že v obidvoch kolekciách bude vždy tá istá množina prvkov. A samozrejme, zavoláme metódu OnListChanged s príslušným parametrom:
protected override void OnClearComplete() { if(isSorted) { originalArray.Clear(); } OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); } protected override void OnInsertComplete(int index, object value) { if(isSorted) { originalArray.Add(value); } OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index)); } protected override void OnRemoveComplete(int index, object value) { if(isSorted) { originalArray.Remove(value); } OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); } protected override void OnSetComplete(int index, object oldValue, object newValue) { if(isSorted) { int indexInOriginal = originalArray.IndexOf(oldValue); originalArray[index] = newValue; } if(oldValue != newValue) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); } }
No a čo sa skupiny okolo udalostí týka, musíme ešte implementovať vlastnosť SupportsNotification, ktorá bude vždy vracať true:
public bool SupportsChangeNotification { get { return true; } }
No a na úplný záver zostali už len veci, týkajúce sa rozhrania ICollection. Prístupvé členy IsSynchronized a SyncRoot. Tieto neimplementujeme a teda vytvorená kolekcia nebude thread-safe.
public bool IsSynchronized { get { return false; } } public object SyncRoot { get { return null; } }
A na záver, metóda CopyTo, ktorá položky kolekcie skopíruje do poľa (Array). Na samotné kopírovanie sa použije metóda CopyTo vnorenej kolekcie (InnerList).
public void CopyTo(Array array, int index) { InnerList.CopyTo(array, index); }
A to je ozaj všetko. Ako som už spomínal, hneď nasledujúcim krokom u mňa bolo vytvorenie šablóny pre CodeSmith, ale tá je natoľko triviálna, že sa dá veľmi ľahko obísť. Stačí, ak si v uvedených členoch vytvorenej kolekcie necháte nahradiť triedu (text) Customer inou (iným textom), práve tou, ktorej silne typovú kolekciu chcete mať...
Ak nechceš premeškať príspevky ako je tento, sleduj ma na Twitteri, alebo ak máš RSS čítačku, môžeš sledovať môj RSS kanál.