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:
). 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" 