Delegaatit ja tapahtumat
- Luento Youtubessa
- tjlahton2012-02-07_1516.mp4 35.5 Mt
- tjlahton2012-02-07_1516.wmv 57.4 Mt
- tjlahton2012-02-07_1516.mp3 18.8 Mt
Tutustutaan hieman paremmin tapahtumankäsittelyyn (events) ja delegaatteihin. Opitaan määrittelemään omia delegaatteja ja tapahtumia omissa luokissa.
Luentoesimerkki (Esimerkki zip-paketissa)
Delegaatit- ja tapahtumat esimerkki (Esimerkki zip-paketissa)
Tapahtumat
- Joku aiheuttaa tapahtuman: kiinnostuneet reagoivat siihen
- Tapahtumalla voi olla useita "kuulijoita". Sama kuulija voi seurata useita tapahtumia kerralla
- Tapahtuma jolla ei ole seuraajia ei myöskään koskaan tapahdu
- Tapahtumilla viestitään usein käyttäjän tekemisistä esim. painikkeiden painalluksista, menuvalinnoista jne.
- .NET-ympäristössä tapahtumat perustuvat EventHandler-delegaattiin ja EventArgs-luokkaan
delegate void EventHandler(object sender, EventArgs e);
Delegaatit

Delegaatti on sama asia kuin funktio-osoitin. Delegaattien avulla voidaan vasta ohjelman suoritusaikana päättää mitä funktiota kutsutaan.
Delegaatteja käytetään erityisesti tapahtumapohjaisessa ohjelmoinnissa eli esim. windows-ohjelmoinnissa.
- Määritellään delegaatti
- Delegaattimäärittelyn palautustyyppi ja parametrit määräävät millaista funktiota voidaan käyttää
public delegate int Esimerkki(); public delegate void Esimerkki2(object sender, EventArgs e); // windows forms -tapahtumat
- Tapahtuman aiheuttavassa luokassa luodaan delegaattityyppinen tai event delegaatti -tyypinen muuttuja:
public Esimerkki tapahtuma; public event Esimerkki2 tapahtuma2;
event-sana aiheuttaa tiettyjä rajoituksia: tapahtumaa voidaan kutsua vain luokan sisältä, event voidaan asettaa ja poistaa +=- ja -=-operaattoreilla ja tapahtuma pitää aina olla muotoa tapahtuma(object source, EventArgs e)
- Jossain vaiheessa olion elämää se kutsuu delegaattiaan eli aiheuttaa tapahtuman:
if ( tapahtuma != null) tapahtuma(); if (tapahtuma2 != null) tapahtuma2(this, e);
- Tapahtumalla pitää kuitenkin olla myös seuraaja eli joku, joka on luonut edellämainittua
luokkaa olevan olion ja määritellyt seuraajan tapahtumalle:
Foo joku = new Foo; joku.tapahtuma = new Esimerkki(funktio); // jos delegaatti palauttaa jotain niin vain yksi mahdollinen seuraaja joku.tapahtuma2 += new Esimerkki2(funktio2); // jos delegaatti ei palauta mitään ja mahdollista olla useampi seuraaja public int funktio() { } public void funktio2(object sender, EventArgs e) { } - funktiota kutsutaan aina kun tapahtuu!
- Delegaattimäärittelyn palautustyyppi ja parametrit määräävät millaista funktiota voidaan käyttää
Tapahtumankäsittely explained
Idea on seuraava ajateltuna käyttämisen kannalta:
- Luot uuden Windows Forms -ohjelman eli aloitat ohjelman tekemisen tyhjällä lomakkeella.
- Haluat lomakkeelle painikkeen, jota painaessa esim. lomakkeen title-teksti vaihtuu
- Asetat siis painikkeen Click-tapahtumaan koodia, jonka haluat suoritettavan painiketta klikatessa. Teet tämän joko tuplaklikkaamalla painiketta tai etsimällä Events-listasta tuon Click-tapahtuman ja pääset kirjoittamaan haluamasi koodin
-
Mitä jos haluaisit määritellä dynaamisesti ohjelman ajon aikana tämän
koodin joka tapahtuu klikatessa? No sekin onnistuu eli lomakkeen koodissa
yhdistät painikkeen OnClick-tapahtumaan oman funktion jotenkin seuraavalla
tavalla:
Painike.Click += new System.EventHandler(PainikeKlikattu);
PainikeKlikattu on tässä kohtaa itse kirjoitettu metodi. System.EventHandler on delegaattityyppi jota Painike.Click vastaa
No mitäs jos tarkoitus on tehdä vastaavanlainen toiminta omaan komponenttiin eli haluat pystyä lomakkeessa tai jossain muussa ympäristössä "kuuntelemaan" mitä komponenttisi tekee.
Omassa komponentissa nämä onnistuvat samaan tapaan kuin PositiveNumberTextBoxissa eli pitää tehdä seuraavat:
Määritellään oma delegaattityyppi
public delegate void NegativeNumberHandler();
luodaan tämän oman delegaattityypin tyyppinen Event
public event NegativeNumberHandler OnNegativeNumber;
tämä event on käytännässä vain funktio-osoitin, jonka osoittamaa funktiota kontrolli kutsuu aina kun syötteenä on negatiivinen luku
Kolmanneksi se tärkein eli positivenumbertextboxissa kutsutaan luotua delegaattieventiä kuin se olisi tavallinen metodi. Kyseessä on siis funktio-osoitin. Kutsu tehdään silloin kun oma komponentti katsoo sen oikeaksi eli tässä tapauksessa silloin kun syötteenä on negatiivinen numero. Kutsussa pitää aina tarkistaa, että tuo event eli OnNegativeNumber on erisuuri kuin null. Jos tuo on null niin se tarkoittaa, että kukaan ei seuraa tapahtumaa eli esim. lomakkeella johom negativetextbox on raahattu, ei ole asetettu mitään funktiota tämän komponentin OnNegativeNumber-tapahtumaan. Jos taas eri suuri kuin null niin kaikki mahdolliset seuraavat funktiot kutsutaan. Kyseessä on siis oikeastaan funktio-osoitinlista koska samaa metodia voi seurata useampikin.
Alussa mainitussa painikkeessa, joka on siis valmiina tarjolla oleva Button-luokka, on siis jossain paikassa jokin tämänsorttin kutsu:
if (Click != null) Click();
jos halutaan liikutella tapahtumaliikenteessä parametreja niin sitten tarvitaan oma EventArgs-luokasta peritty luokka ja liikutellaan sitä mukana:
LiikkuvaAuto.csLiikkuvaAuto-luokassa ajastin_Tick-metodista näkee tuon käytön ja koodinlopussa on peritty oma luokka eventargsista.

Käyttäjien kommentit