Zdarzenia to wszelkie interakcje użytkownika z naszym programem, takie jak: wciśnięcie przycisku na klawiaturze, ruch myszką, itd., lub różne zachowania aplikacji takie jak wysyłanie powiadomień. Aplikacje muszą reagować na zdarzenia w momencie ich wystąpienia. Zdarzenia są używane do komunikacji między procesami.

Zdarzenia są deklarowane i wywoływane w klasie oraz połączone mechanizmem obsługi zdarzeń za pomocą delegatów w obrębie tej lub innej klasy. Klasa zawierająca zdarzenia jest używana do zarejestrowania tego zdarzenia.

Klasa, w której definiujemy nasze zdarzenie to tzw. „publisher”. Z kolej klasa, która odbiera to zdarzenie to tzw. „subscriber”.


Deklarowanie zdarzeń

Aby zadeklarować zdarzenie wewnątrz klasy w pierwszej kolejności należy przygotować delegat:

public delegate void SampleLogHandler(string status);

Następnie przy użyciu słowa kluczowego event należy przygotować deklarację zdarzenia na podstawie powyższego delagata:

public event SampleLogHandler SampleEventLog;

Powyższy kod definiuje delegata o nazwie SampleLogHandler oraz zdarzenie o nazwie SampleEventLog, który wywoła delegata w momencie wzniesienia zdarzenia (wywołania).


Przykład

Tradycyjnie już koncepcje łatwiej będzie zrozumieć na gotowym przykładzie z opisem:

using System;
namespace Zdarzenia
{
    class TestowanieZdarzen
    {
        public int value;
        // Deklaracja delegata
        public delegate void NumberManipulationHandler();
        // Deklaracja zdarzenia
        public event NumberManipulationHandler ChangeNumber;
        // Metoda aktwyująca zdarzenie
        protected virtual void OnNumberChanged()
        {
            if (ChangeNumber != null)
                ChangeNumber();
            else
                Console.WriteLine("Zdarzenie!");
        }
        public TestowanieZdarzen(int i)
        {
            SetValue(i);
        }
        // Ustawianie wartości dla liczb
        // Jeżeli podana liczba jest różna od liczby aktualnej
        // wywołujemy metodę związaną ze zmianą liczby
        public void SetValue(int i)
        {
            if(value != i )
            {
                value = i;
                OnNumberChanged();
            }
        }
        static void Main(string[] args)
        {
            TestowanieZdarzen tz = new TestowanieZdarzen(5);
            tz.SetValue(8);
            tz.SetValue(16);
            Console.ReadKey();
            // Wynik działania programu
            // Zdarzenie!
            // Zdarzenie!
            // Zdarzenie!
        }
    }
}

Przykład nr 2

Przykład ten jest związany z prostym przeglądem naszego samochodu. Kiedy mechanik podłącza samochód pod komputer, przykładowe dane z systemu są automatycznie zapisywane do pliku wraz z uwagami serwisanta. Poniższy opis programu jest dużo bardziej szczegółowy niż w pierwszym przykładzie.

using System;
namespace ZdarzeniaSerwis
{
    class CarsComputer
    {
        // Będziemy zapisywać dane związane z temperaturą cieczy chłodzącej
        // oraz jej ciśnieniem
        private int temperature;
        private int pressure;
        public CarsComputer(int t, int p)
        {
            temperature = t;
            pressure = p;
        }
        // Metoda do pobierania temperatury
        public int GetTemperature()
        {
            return temperature;
        }
        // Metoda do pobierania ciśnienia
        public int GetPressure()
        {
            return pressure;
        }
    }
    // Ta klasa to tzw. publisher, tj. klasa w której zdefiniujemy zdarzenie
    class DelegateOnBoardComputerEvent
    {
        // Deklarujemy delegat, którego użyjemy do defincji zdarzenia
        public delegate void CarsComputerHander(string info);
        // Deklarujemy zdarzenie na podstawie powyższego delegata
        public event CarsComputerHander CarsComputerEventLog;
        // Proces sprawdzania i logowania danych z komputera pokładowego
        public void LogProcess()
        {
            string information = "OK";
            CarsComputer oc = new CarsComputer(80, 12);
            int t = oc.GetTemperature();
            int p = oc.GetPressure();
            if (t > 70 || p > 15)
                information = "Dokonaj dokładnego przeglądu!";
            OnCarsComputerEventLog("Zapisywanie informacji: \n");
            OnCarsComputerEventLog("Temperatura: " + t + "| Ciśnienie: " + p);
            OnCarsComputerEventLog("Informacja: " + information);
        }
        protected void OnCarsComputerEventLog(string information)
        {
            // CarsComputerEventLog to nasze zdarzenie, które jest zdefiniowane na podstawie 
            // istniejącego delegata CarsComputerHander
            // Delegat ten jest sygnaturą metody, króra jest wykorzystywna w naszym zdarzeniu
            // Dlatego też, jako parametr naszego zdarzenia przekazujemy 'string'
            if (CarsComputerEventLog != null)
            {
                CarsComputerEventLog(information);
            }
        }
    }
    // Ta klasa to tzw. subscriber, tj. klasa, która odbiera zdarzenie
    class Program
    {
        // Metoda dzięki, której wyświetlimy wszystkie informacje w konsoli
        static void DisplayInformation(string info)
        {
            Console.WriteLine(info);
        }
        static void Main(string[] args)
        {
            // Tworzymy obiekt klasy DelegateOnBoardComputerEvent
            DelegateOnBoardComputerEvent carCompterEvent = new DelegateOnBoardComputerEvent();
            // Aby wyświetlić informacje z naszego komputera pokładowego musimy w jakiś sposób
            // połączyć się z metodą DisplayInformation, która te informacje wyświetla
            // Metoda ta ma taką samą sygnaturę jak nasz delegat...
            // Możemy zatem do naszego zdarzenia podpiąć metodę DisplayInformation(info)
            carCompterEvent.CarsComputerEventLog += new DelegateOnBoardComputerEvent.CarsComputerHander(DisplayInformation);
            // Wszystko jest już przygotowane - zdarzenia są gotowe
            // W momencie wywołania zdarzenia CarsComputerEventLog dojdzie do wywołania naszej metody do wyświetlania danych 
            // w konsoli. 
            // Wywołujemy proces przetwarzania danych
            carCompterEvent.LogProcess();
            Console.ReadKey();
            // Wynik działania programu
            // Zapisywanie informacji:
            //
            // Temperatura: 80 | Cisnienie: 12
            // Informacja: Dokonaj dokladnego przegladu!
        }
    }
}