Drin...Drin...
"Ciao, Igor. Senti, vorrei una
modifica al tuo software di fatturazione.
Quando scegli il cliente sulla
maschera delle fatture, non voglio cliccare sui tre puntini.
Io so il codice,
per cui mi piacerebbe inserire una cosa tipo COD021, ed automaticamente deve
apparire il nome del cliente. Si può fare? Ma la fai? Ci metti
tanto?"
Ovviamente, è solo una telefonata virtuale e mai avvenuta. Solo che potrebbe
essere una cosa interessante da fare.
Vediamo come modificare la mia
applicazione per implementare questa modifica.
Un breve riassunto
Nella mia soluzione, ho definito una
form FormFattura. All'interno di questa form, ho creato un metodo privato
SetupDatabindings che si occupa di attivare il binding tra il
business object ed i controlli, passando attraverso un componente BindingSource
come raccontavo ieri mattina. Fino a pochi minuti
fa, il binding sulla TextBox del cliente era:
txtCliente.DataBindings.Add("Text", bndSrc, "Cliente", true);
Ho fatto l'override del metodo ToString() nel business
object, per cui nella TextBox appare la ragione sociale del cliente. La riga qui
sopra crea implicitamente un oggetto Binding. Per soddisfare
l'ipotetico cliente, devo modificare il binding e crearlo esplicitamente, avendo
cura di settare qualcosa in più:
Binding bndCliente = new Binding("Text", bndSrc, "Cliente", true);
bndCliente.DataSourceNullValue = 0;
bndCliente.NullValue = "(Inserire il codice del cliente oppure selezionarlo dall'elenco)";
bndCliente.Parse += new ConvertEventHandler(bndCliente_Parse);
txtCliente.DataBindings.Add(bndCliente);
La proprietà NullValue è quella che appare nella TextBox
quando il DataMember Cliente vale null. Gestisco
l'evento Parse, che si scatena quando l'utente inserisce
qualcosa nel controllo, e se ne va (nel senso che preme TAB, o clicca da qualche
altra parte...il caffè non c'entra nulla! ). L'evento viene ovviamente gestito da un handler, che
si presenta come segue:
void bndCliente_Parse(object sender, ConvertEventArgs e)
{
// Arrivo qui quando l'utente inserisce qualcosa
// a mano nella TextBox
string text = txtCliente.Text;
Cliente cl = (Cliente)new DataProvider<Cliente>().GetInstance("Codice", text);
if (cl != null)
e.Value = cl;
else
e.Value = null;
}
Cosa faccio? Beh, innanzitutto leggo il contenuto della TextBox che l'utente
ha appena modificato. Parto dal presupposto che possa contenere solo il codice,
per cui chiedo al mio data provider di ritornarmi un'istanza della classe
Cliente corrispondente al codice inserito. Se l'istanza è valida, allora la
setto, altrimenti la reimposto a null. Se l'utente
inserisce una schifezza (passatemi il termine), l'oggetto cl è
null, per cui nessun problema. Grazie all'oggetto Binding, quando il cliente è
vuoto (null), la TextBox fa apparire una bella stringa che dice:
(Inserire il codice del cliente oppure selezionarlo dall'elenco)
che può essere utile per dare qualche aiuto all'utente che sta usando il
software.
Conclusioni
Nulla di particolarmente complicato. L'unico
vero svantaggio è che questo meccanismo è molto legato all'interfaccia utente:
si poteva fare diversamente magari con un type converter, cioè indicare al
framework come convertire un oggetto Cliente in string e viceversa. La logica è
sempre la stessa, ma applicata diversamente.
Drin...Drin...
"Ciao, Graziella. Senti, ti ho
appena mandato via e-mail il nuovo assembly. Copialo e sovrascrivilo con quello
vecchio. Provalo, non si sa mai. Cosa....bbzzz.....no, non lo distribuisco con
ClickOnce......
Ok, sì, lo farò.....promesso....adesso ti saluto, ok? Buona
domenica"