Il libro sul data binding sta dando i suoi piccolo 
frutti. Ho migliorato parte del codice del mio sw di fatturazione, con una 
piccola (e banale) chicca a cui sinceramente prima non avevo pensato. Questa 
chicca, a chi dovesse interessare, è spiegata a pag.114 di Data Binding with Windows Forms 
2.0. Così, chi ce  l'ha, può dargli 
un'occhiata...vero, Marco? 
Com'era il mio codice prima...
Dunque, vedrò di essere il 
più breve possibile. In ogni Windows Form del mio sw, faccio vivere 
un'istanza di un oggetto, dipendentemente dalla form stessa. Sulla form degli 
articoli, c'è un oggetto currentEntity di tipo Articolo. Sulla form delle fatture, c'è un oggetto 
currentEntity di tipo Fattura. E così via: 
ovviamente, Articolo e Fattura 
sono entrambi classi definite nel mio domain model.
Ho avuto un piccolo problema, che aveva risolto in un modo poco elegante, che 
ho sistemato questa mattina. L'utente apre la WF dei clienti - supponiamo - 
è la vede completamente vuota. Il binding non è attivo, tutte le TextBox sono 
vuote. Attraverso vari meccanismi (dataset tipizzati, data provider, 
DataGridView, etc.), l'utente sceglie un cliente (magari per 
visualizzarlo) cliccando sul pulsante Sfoglia. Il codice 
che gestisce il click è il seguente:
public override void PulsanteSfoglia(object sender, EventArgs e)
{
    using (FormSfoglia frm = new FormSfoglia())
    {
        frm.DataSetToView = provider.GetDataSetBrowse();
        if (frm.ShowDialog() == DialogResult.OK)
        {
            // aggiorno l'oggetto con quello selezionato dall'utente
            // sulla WF di sfoglia
            refreshEntity((Cliente)provider.GetInstance("Codice", frm.SelectedValue));
            errNotifica.Clear();
            // entro in modalità Modify
            EntityState = FormEntityStateEnum.Modify;
            this.txtCodice.Focus();
        }
    }
}
La form di dialogo ritorna tramite la proprietà 
SelectedValue una stringa che contiene il codice del cliente 
che voglio visualizzarlo. Notare l'uso del metodo privato refreshEntity: a cosa serve? Questo è quello che volevo 
eliminare. La refreshEntity non fa altro che riassegnare una ad una le proprietà 
dell'oggetto Cliente:
private void refreshEntity(Cliente entity)
{
    currentEntity.CAP = entity.CAP;
    currentEntity.Città = entity.Città;
    currentEntity.Codice = entity.Codice;
    currentEntity.Denominazione = entity.Denominazione;
    currentEntity.FareBusta = entity.FareBusta;
    currentEntity.ID = entity.ID;
    currentEntity.Pagamenti = entity.Pagamenti;
    currentEntity.PartitaIva = entity.PartitaIva;
    currentEntity.Password = entity.Password;
    currentEntity.Provincia = entity.Provincia;
    currentEntity.Sigla = entity.Sigla;
    currentEntity.Username = entity.Username;
    currentEntity.Via = entity.Via;
}
Nel blocco di codice qui sopra, l'oggetto entity è il 
nuovo cliente che voglio vedere sulla form, mentre 
currentEntity è il cliente attualmente visualizzato. 
Questo codice è necessario per scatenare l'aggiornamento 
dei controlli bindati, che altrimenti non avviene. Difatti, il 
semplice assegnamento currentEntity = entity è un semplice assegnamento di un 
riferimento, e non passa attraverso le NotifyPropertyChanged definite nel 
business object Cliente. Anche se è necessario, non mi 
piace per nulla: lungo, noioso, soggetto ad errori, mi devo 
ricordare di aggiornarlo se cambio qualcosa nel mio business object. Insomma, 
c'erano tutti i buoni propositi per fare le cose in modo diverso e più 
performante. Come? La risposta è arrivata ieri sera.
Il componente BindingSource
La magia sta nel componente 
BindingSource, che va semplicemente trascinato sulla Windows Forms. 
Non storcete il naso, non ci sono wizard di mezzo. Pensate a 
questo componente come a una sorta di proxy. Nella logica del 
binding, si frappone fra i controlli bindati e la datasource sottostante. 
Possiamo controllare - attraverso una serie di eventi - l'aggiornamento dei 
controlli e del datasource, intercettando il flusso dei dati da e verso una 
certa direzione. Ma la cosa interessante è che settare 
una nuova datasource provoca automaticamente l'aggiornamento di tutti i 
controlli bindati a tale datasource. Mi spiego meglio:
#region SetupDataBindings()
private void SetupDataBindings()
{
    if (!activeBinding)
    {
        bndSrc.DataSource = currentEntity;
        txtCodice.DataBindings.Add("Text", bndSrc, "Codice");
        txtRagioneSociale.DataBindings.Add("Text", bndSrc, "Denominazione");
        txtVia.DataBindings.Add("Text", bndSrc, "Via");
        txtCAP.DataBindings.Add("Text", bndSrc, "CAP");
        txtCittà.DataBindings.Add("Text", bndSrc, "Città");
        txtProv.DataBindings.Add("Text", bndSrc, "Provincia");
        txtPartitaIva.DataBindings.Add("Text", bndSrc, "PartitaIva");
        txtTipoPagamento.DataBindings.Add("Text", bndSrc, "Pagamenti");
        txtSigla.DataBindings.Add("Text", bndSrc, "Sigla");
        txtUsername.DataBindings.Add("Text", bndSrc, "Username");
        txtPassword.DataBindings.Add("Text", bndSrc, "Password");
        activeBinding = true;
    }
}
#endregion
Mentre prima bindavo direttamente datasource e controlli, adesso passo 
attraverso il BindingSource bndSrc. Questo è il primo punto. Il secondo 
punto, che sbroglia la matassa, è che adesso la brutta refreshEntity non mi 
serve più. Quando l'utente sceglie un nuovo cliente, mi basta semplicemente 
reimpostare il datasource del BindingSource e tutti i controlli vengono 
aggiornati.
// ...codice, codice, codice
// aggiorno l'oggetto con quello selezionato dall'utente
// sulla WF di sfoglia
currentEntity = (Cliente)provider.GetInstance("Codice", frm.SelectedValue);
bndSrc.DataSource = currentEntity;
// ...codice, codice, codice
Questo è un codice molto più pulito, snello ed efficiente. Che dire, evviva 
il data binding una volta di più!!! 