La Study Guide che sto usando come scaletta presenta molti aspetti del framework che vanno imparati e vanno saputi per approdare a MCAD. I concetti espressi sono diversi, e vanno da ADO.NET, alla localizzazione delle applicazioni, dalla validazione dell'utente, a come debuggare correttamente il codice usando le classi relative al Debug e al Trace.
Ieri pomeriggio, che era una domenica fredda e piovosa, mi sono messo lì con il mio Visual Studio 2003 a casa ed ho creato l'applicazione di base che mette realmente in piedi i concetti espressi fino a questo momento. L'applicazione ha le seguenti caratteristiche (uno screenshot è qua)
- usa un solo Windows Form con una UI bella (beh, dipende dai gusti )
- usa l'ErrorProvider per segnalare all'utente gli errori di validazione
- usa la classe Age che ho descritto in questo post
- i sorgenti dell'applicazione sono liberamente scaricabili da qua
Nei prossimi articoli vedrò di espandere questa applicazione, implementando la localizzazione, creando un MainMenu e un ContextMenu da qualche parte, inventandomi qualcosa per ADO.NET (esportazione in XML o salvataggio dei dati su una tabella di SQL Server, etc.) e così via.
Oggi però non vi voglio lasciare a stomaco vuoto, perciò annoterò e descriverò le migliorie che credo di aver apportato al codice. Sostanzialmente, non è molto cambiato, però qualcosa di interessante c'è secondo me, perciò....ecco qua!!!
Funzionalità nella versione corrente
Come funziona? Sulla WF adesso chiediamo qualcosa in più: il nome della persona in questione e la sua data di nascita (non più l'anno solamente). Ho messo una ListBox nella parte inferiore della WF: inseriamo il nome (es: "Mario Rossi"), inseriamo la sua data di nascita (es: "10/11/1968") e clicchiamo sul pulsante Get Age. Nella ListBox viene aggiunta una voce che dice: "Mario Rossi is 37 years old". Uao!
La validazione dei dati
Per validare i dati, ho creato una function validate() il cui codice è:
private bool validate()
{
DateTime dt;
string msg = string.Empty;
// check for name of person
if (this.txtName.Text.Length == 0)
msg = "Name cannot be empty! Please insert name of this person!";
this.errMsg.SetError(this.txtName, msg);
// check for birthdate
msg = string.Empty;
if (this.txtBirthDate.Text.Length != 10)
msg = "This is not a valid date! Please correct!";
try
{
dt = Convert.ToDateTime(this.txtBirthDate.Text);
if (dt.Year < 1850)
msg = "This person is too old, are you sure?";
if (dt > System.DateTime.Now)
msg = "Are you sure? This person is born in the future!";
}
catch
{
msg = "This is not a valid date! Please correct!";
}
this.errMsg.SetError(this.txtBirthDate, msg);
return(msg.Length > 0);
}
Questa function valida tutti i control sulla WF: viene richiamata da ogni evento Validating di ogni controllo sulla WF. In questo modo, ho un'unica function centralizzata che si occupa di tutto. Se devo correggere qualcosa nel processo di validazione, cerco la validate() e correggo lì. La logica è quella esposta nei post precedenti: uso una string msg per definire l'eventuale messaggio di errore su ogni control della WF. Nota importante: la string msg viene resettata a string.Empty quando si passa da un control all'altro. Questo perchè se un control fallisce la validazione, mi trascino il suo error message al control successivo.
La validate() ritorna un bool per il semplice fatto che il suo valore di ritorno viene impostato alla proprietà Cancel del parametro e di ogni evento Validating. Ad esempio:
private void txtName_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = validate();
}
private void txtBirthDate_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = validate();
}
Ed il gioco è fatto!!!
Proprietà e metodi della classe Age
La classe Age ha tre proprietà: Name, BirthDate e Phrase. Le prime due sono semplicemente i membri che contengono nome e data di nascita. La terza è una proprietà un po' speciale, che ritorna una stringa. E' una property read-only: ovvero in sola-lettura, in quanto ritorna semplicemente la stringa che andiamo ad aggiungere alla ListBox. Avremmo potuto fare meglio facendo l'overloading di ToString(): in questo modo avremmo potuto fare direttamente:
this
.lstResults.Items.Add(myAge);
(come avrebbe potuto essere l'evento Click del btnCalculate)
Nelle versioni future aggiungeremo proprietà e metodi per dire, ad esempio, quanto manca o quanto è passato dal nostro compleanno. Scopo? Boh!!!!
Localizzazione dell'applicazione
Usando le classi descritte nella Study Guide di Lorenzo, vedrò di localizzare l'applicazione usando i file di risorsa previsti dal framework e la classe CultureInfo.
ADO.NET
Poi, passeremo a salvare l'elenco delle persone su un file XML, lo rileggeremo, faremo data-binding, insomma giocheremo un po' con quello che il framework ci mette a disposizione.
Beh, scaricatevi il sorgente, dategli un'occhiata e distruggetemi, come al solito!!!
Compito a casa (che io non sono riuscito a risolvere): per chi utilizza FxCop, ho provato a dare in pasto un assembly contenente solo la mia classe Age, ma con scarsi risultati . Chi ha voglia di far validare questa classe, alzi la mano!!!