Uno dei punti della Study Guide di Lorenzo parla di come
creare e gestire gli eventi delle Windows Forms di .NET. Parto dal presupposto
che sappiate cosa sia il framework, come funzioni l'IDE di Visual Studio e
conosciate almeno le basi di C# o VB.NET per programmare.
Gestire un evento significa scrivere una function che
faccia un qualcosa quando quell'evento
accade. Per esempio, un button può essere cliccato, una Windows Form
(WF) può essere ridimensionata o ridotta ad icona, una combobox può essere "aperta"
(passatemi il termine). Se vi interessa fare un qualcosa in certe occasioni (interazione
con l'utente), basta scrivere una function che faccia quel qualcosa. Come? In
C#, il metodo più comodo è usare la Property Window come ho scritto in questo post del mio blog. In breve, supponiamo di avere una WF, di
avere un pulsante e di voler far apparire una MessageBox quando l'utente clicca.
Apriamo la WF, apriamo la Property Window (PW), clicchiamo sul pulsantino con il
lampo e facciamo doppio-click sulla riga corrispondente all'evento Click. In
teoria avremmo potuto fare doppio-click sul button, ma francamente con C# è un approccio che non mi piace, perchè crea l'evento di default per l'oggetto,
ma impedisce la creazione degli handler per gli altri eventi (in attesa
di essere smentito). Il codice che appare è (la MessageBox è ovviamente inserita a mano,
.NET mica se lo sogna!):
private void btnSaluta_Click(object sender, System.EventArgs e)
{
MessageBox.Show("Ciao Mondo!");
}
Ecco fatto! Ma questo
probabilmente lo sapevamo già fare. Noi che vogliamo arrivare ad essere MCAD,
diamo un'occhiata più da vicino a quello che succede. Ragionando un po' su
quello che scrissi l'altra volta, scopriamo che abbiamo delle potenzialità in
più con .NET. In pratica, qualsiasi function può diventare l'handler per
un certo evento, l'unico requisito è che la
sua firma sia identica a quella prevista del framework.
Quindi io mi posso scrivere una function simile a questa:
private void salutaMondo(object sender, System.EventArgs
e)
{
MessageBox.Show("Ciao Mondo, versione
personalizzata!");
}
Ricompiliamo, eseguiamo il codice e clicchiamo sul pulsante. Non
è cambiato nulla. Come fa il framework a capire quale function eseguire
per un certo evento? Diamo un'occhiata al costruttore della nostra WF:
viene eseguita la function InitializeComponent(). Vediamo il codice: per chi
viene dal vecchio Visual Studio (come me, Visual Basic 6.0), quello che si
presenta davanti agli occhi è una meraviglia. In pratica, l'IDE di VS crea
codice, codice, codice per tutti gli oggetti che abbiamo sul WF, li istanzia,
assegna le proprietà in base a quello che diciamo nella PW, e così via. Nulla è
più nascosto, tutto viene fatto a run-time. Se vediamo il codice relativo al
button btnSaluta, per esempio, vediamo che è:
//
//
btnSaluta
//
this.btnSaluta.Location = new System.Drawing.Point(8, 8);
this.btnSaluta.Name =
"btnSaluta";
this.btnSaluta.Size = new System.Drawing.Size(96, 23);
this.btnSaluta.Text = "Saluta il
mondo!";
this.btnSaluta.Click += new System.EventHandler(this.btnSaluta_Click);
// qualche riga
dopo, il codice esegue una cosa tipo questa:
this.Controls.Add(this.btnSaluta);
Impariamo bene questo, perchè è uno dei requisiti per
MCAD. In breve, creare un nuovo oggetto a run-time e posizionarlo sulla
WF. Sorpresa, ecco una riga interessante:
this.btnSaluta.Click += new System.EventHandler(this.btnSaluta_Click);
Questa riga associa all'evento Click del button
btnSaluta la function btnSaluta_Click(). Notate l'eleganza di C# rispetto a
VB.NET, quest'ultimo usa lo statement AddHandler per fare la stessa cosa. In C#
è possibile effettuare l'overloading degli operatori, e per questo si usa
l'operatore '+'. Quindi, tutto quello che dobbiamo fare per cambiare la function
da eseguire per un certo evento è sostituire la riga con:
this
.btnSaluta.Click += new System.EventHandler(this.salutaMondo);
Compiliamo, eseguiamo e
clicchiamo. Il messaggio è cambiato, perchè adesso sull'evento Click del button
viene eseguita la nostra salutaMondo(). Attenzione: la cosa divertente è che
possiamo modificare gli handler degli eventi anche a run-time (in realtà
anche adesso lo è, perchè il codice che abbiamo appena modificato è nel
costruttore). Aggiungiamo un altro pulsante (btnCambiaHandler) e scriviamo
l'evento Click fino ad ottenere quanto segue:
private void
btnCambiaHandler_Click(object sender, System.EventArgs e)
{ this.btnSaluta.Click += new System.EventHandler(this.btnSaluta_Click); }
Questo reimposta
l'handler del pulsante btnSaluta. Compiliamo il codice, eseguiamo. Clicchiamo il
pulsante Saluta: cosa succede? Vediamo due messaggi, giusto? In questo momento,
l'evento Click del btnSaluta viene gestito da due function, una dopo l'altra, in
base all'ordine con cui le abbiamo assegnate. Per chi proviene dai vecchi VS,
questa è un'altra piccola meraviglia. Non so bene chi utilità possa avere, però
intanto lo possiamo fare. :-) Per sostituire l'handler per l'evento, avremmo
dovuto scrivere:
private void
btnCambiaHandler_Click(object sender, System.EventArgs e)
{
this.btnSaluta.Click -= new System.EventHandler(this.salutaMondo);
this.btnSaluta.Click += new System.EventHandler(this.btnSaluta_Click);
}
Con questo primo post, sono stati toccati diversi temi presi di
mira dall'esame MCAD (eventi, handler degli eventi, creazione di oggetti a
run-time). Molto spesso, è fondamentale per me sapere qual'è l'evento migliore
per ottenere un certo risultato. Un altro aspetto che vorrei coprire è l'uso
dell'evento Validating della TextBox e di altri controlli, a
cui è stato dedicato un paragrafo nella Study Guide di Lorenzo.
Commentate pure, correggetemi, fate precisazioni, migliorate il
contenuto del post!