Jako, że już sporo czasu pracuje w C# jako narzędziu, gdzie szybko można robić narzędzia (paradoksalnie) z przyjaznym interfejsem – w dodatku szybko i wygodnie, to w pewnym momencie musiałem dodać do nowej klasy własnego tzw. “Event’a” (trigger’a, wyzwalacz, zdarzenie, czy jak to zwą). Jak to zrobić było oczywiście napisane w Bibliotece MSDN, aczkolwiek trzeba było dokładnie wiedzieć czego się szuka, żeby tam dotrzeć.
No ok – przyjrzyjmy się strukturze tego Event’a.
public event EventHandler CosZrob;
Jak wiadomo słowo “public” udostępnia dane pole klasy na zewnątrz, a “CosZrob” jest nazwą danego pola. “Event” oczywiście deklaruje, że mamy do czynienia ze zdarzeniem. Najciekawszy jest “EventHandler”. Jest to tzw. “delegat”, czyli twór programistyczny wyspecjalizowany w funkcjonalności do przechowywania adresów metod tej klasy, czy innej klasy – widać tu zagubioną funkcjolność C++ do przechowywania adresów metod klas. Samo słowo kluczowe delegate ma trochę więcej funkcjonalności (jak, np. tworzenie beznazwowych metod), lecz nam się przyda do czego innego. “EventHadnler” jest już wbudowanym delegatem, mający już określoną strukturę – jego deklaracja powinna wyglądać mniej-więcej tak (jak zresztą napisane to jest w MSDN):
public delegate void EventHandler( object sender, EventArgs e );
Jak widać strukturą przypomina deklarację funkcji. Pierwszy argument jest chyba oczywisty, drugi natomiast przedstawia klasę stworzoną w celu właśnie użycia w eventach:
public class EventArgs { public static readonly EventArgs Empty; public EventArgs(); }
Jak widać klasa jest prościutka – jest podstawą tworzenia tzw. argumentów zdarzenia. Jako że chce stworzyć zdarzenie posiadające własne argumenty (a nie pusty zapełniacz), więc muszę napisać trochę kodu:
public class CosEventArgs : public EventArgs { public string Cos { get; set; } public CosEventArgs( string _Cos ) { Cos = _Cos; } }
Ok, teraz chciałbym użyć tak stworzonego elementu. Dlatego jestem zmuszony stworzyć nowego delegata dla takiego zadania, co by przyjmował moją nową klasę:
public delegate void CosEventHandler( object sender, CosEventArgs ce );
Mała uwaga – wcale nie musimy używać EventArgs przy tworzeniu delegata – możemy go olać. Struktura argumentów może być dowolna – to co teraz piszemy jest po prostu ustaloną konwencją, żeby wszystko miało ręce i nogi – chociaż i widziałem zastąpienie EventArgs np. string’iem.
Ok – jest już EventHandler – teraz należało by go użyć.
public event CosEventHandler CosZrob;
To już jest w praktyce gotowy do działania event – będzie widoczny na odpowiedniej zakładce VisualStudio we właściwościach obiektu. Inna sprawa, że tworzenie Eventu jest bez sensu, o ile go się gdzieś nie będzie wywoływało, np. W jakieś metodzie:
CosZrob.Invoke( this, new CosEventArgs( "Coś Zrobiłem" ) );
A dalej obsługa eventu przebiega tak jak zwykle. Została ostatnia kwestia – pilnowanie, żeby sam Event nie był pusty – wywołanie w takim przypadku metody Invoke, skończy się błędem. Najłatwiej jest to zrobić, ładując do środka metodę – kukłę.
void OnCosZrob( sender object, CosEventArgs ce ) { } ... //gdzieś w kodzie inicjującym CosZrob += new CosEventHandler( OnCosZrob );
Oczywiście nic nie stoi na przeszkodzie, żeby dany kod “kukiełkowy” od razu coś robił. Trzeba tylko pamiętać działanie operatora “+=” – wszelkie metody jakie za jego pomocą zostaną przypisane do eventu zostaną wywołane (wszystkie!) przy wywołaniu Invoke. Jeżeli chcemy się jakiegoś pozbyć – używamy operatora “-=”.
Nie musisz tworzyć nowego delegata, EventHandler doskonale poradzi sobie z twoim CosEventArgs jako parametrem
ciekawe