Technology Experience

Contenuti gestiti da Igor Damiani
posts - 949, comments - 2741, trackbacks - 15120

My Links

News

  • Questo blog si propone di raccogliere riflessioni, teoriche e pratiche, su tutto quello che riguarda il world-computing che mi sta attorno: programmazione in .NET, software attuale e futuro, notizie provenienti dal web, tecnologia in generale, open-source.

    L'idea è quella di lasciare una sorta di patrimonio personale, una raccolta di idee che un giorno potrebbe farmi sorridere, al pensiero di dov'ero e cosa stavo facendo.

    10/05/2005,
    Milano

Archives

Post Categories

Generale

Le piccole magie del componente BindingSource

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ù!!!

powered by IMHO 1.3

Print | posted on venerdì 28 aprile 2006 14:07 | Filed Under [ Tecnologia ]

Feedback

Gravatar

# L'evento Parse del BindingSource...ed il cliente

30/04/2006 02:06 | Technology Experience
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET