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

[MCAD.21] Completiamo le operazioni di caricamento, salvataggio e di importazione su file XML

Eccomi, direttamente dal mio giardino, pronto per andare avanti e riprendere un attimo il discorso che avevamo lasciato in sospeso mercoledì scorso. Nel mio ultimo post avevamo visto come salvare in un file XML i compleanni che abbiamo inserito nella ListBox, ovvero:

  1. abbiamo aggiunto qualche voce al nostro MainMenu per prevedere le funzioni di caricamento, di salvataggio e di importazione dei nostri files XML
  2. abbiamo visto la creazione e l'utilizzo della function dichiarata così:
    private DataTable getSaveTable(bool WithData)
  3. abbiamo visto l'utilizzo di SaveFileDialog che consente all'utente di scegliere dove salvare il file e con quale nome
  4. abbiamo visto, infine, il metodo WriteXML del DataSet che scrive su disco il file XML (appunto) contenente schema e dati della nostra classe

Operazione di caricamento da file XML
Nel post di oggi vediamo di fare il percorso inverso, ovvero di implementare il caricamento da file XML. Innanzitutto, facciamo così: io ho aperto l'applicazione e ho inserito il mio compleanno, quello di mio fratello e quello dei miei genitori. Ho salvato il file con il nome CompleanniFamiglia.xml, sul Desktop. Quello che vogliamo fare è, in breve: usare la classe OpenFileDialog per dare all'utente la possibilità di scegliere quale file caricare, usare un DataSet e riempirlo con i dati provenienti dal file ed infine popolare la ListBox con questi dati. Presto fatto, qui sotto vi riporto il codice, che descriverò ancora più sotto.

private void mnuLoad_Click(object sender, System.EventArgs e)
{
    
// Creo un'istanza OpenFileDialog
    
OpenFileDialog dlgOpen = new OpenFileDialog();
    
// Imposto alcune property per facilitare l'usabilità
    
dlgOpen.CheckPathExists = true;
    dlgOpen.AddExtension = 
true;
    dlgOpen.Filter = "Files XML|*.xml";

    
if (dlgOpen.ShowDialog() == DialogResult.OK)
    {
        
// creo un dataset
        
DataSet dsBirthdays = new DataSet();
        
// leggo i dati dal file XML salvato
        
dsBirthdays.ReadXml(dlgOpen.FileName);
        
        
this.lstResults.Items.Clear();
        
for(int i=0; i < dsBirthdays.Tables[0].Rows.Count; i++)
        {
            DataRow dr = dsBirthdays.Tables[0].Rows[i];
            Age ageTemp = 
new Age(Convert.ToString(dr["Name"]), Convert.ToDateTime(dr["BirthDate"]));
            
this.lstResults.Items.Add(ageTemp);
        }

        
// Dopo il caricamento, libero la memoria
        
dsBirthdays.Dispose();
    }

    dlgOpen.Dispose();
}

Dunque, vediamo i concetti. Istanziamo un oggetto dlgOpen della classe OpenFileDialog, ne impostiamo alcune property per aiutare l'utente e poi chiamiamo il metodo ShowDialog(). Se l'utente seleziona un file questa classe ci ritorna DialogResult.OK: in questo caso possiamo proseguire senza troppi problemi.

Utilizziamo il DataSet dsBirthdays. Chiamo il metodo ReadXML, passando come parametro dlgOpen.FileName. Se l'operazione va a buon fine, dentro il mio DataSet ho appena caricato una tabella con tutti i dati che mi servono. Svuoto la ListBox e comincio un ciclo for...next per aggiungere tanti Item:

for(int i=0; i < dsBirthdays.Tables[0].Rows.Count; i++)
{
    DataRow dr = dsBirthdays.Tables[0].Rows[i];
    Age ageTemp = 
new Age(Convert.ToString(dr["Name"]), Convert.ToDateTime(dr["BirthDate"]));
    
this.lstResults.Items.Add(ageTemp);
}

Per pulizia di codice, dentro il ciclo istanzio un oggetto DataRow, che è a conoscenza della struttura del DataSet: per questo motivo posso chiamare i campi (Column) esattamente con il loro nome reale, che gli era stato attribuito al momento del salvataggio.

Operazione di importazione da file XML
Oh, è arrivato il momento per una piccola domanda. Supponiamo di dare questa applicazione a due persone diverse: io inserisco i compleanni di qualcuno dei miei amici, mio fratello inserisce quelli dei suoi amici. Io ho raggiunto 30 compleanni, supponiamo, e mio fratello 18. Adesso supponiamo di voler unire le due liste. Come possiamo fare? Vi sembra complicato? Lo vediamo subito!

Continuiamo a supporre. Io salvo il mio file con il nome CompleanniAmiciIgor.xml, mentre mio fratello lo salva come CompleanniAmiciOmar.xml. L'obiettivo è quello di caricare uno dei due files, e successivamente importare il secondo. Per questo motivo è stato previsto il menu mnuImport, il cui handler completo di codice è:

private void mnuImport_Click(object sender, System.EventArgs e)
{
    
// istanzio un dataset corrispondente agli items
    // nella ListBox
    
DataSet dsScreen = new DataSet();
    dsScreen.Tables.Add(
this.getSaveTable(true));

    
// Creo un'istanza OpenFileDialog
    
OpenFileDialog dlgOpen = new OpenFileDialog();
    
// Imposto alcune property per facilitare l'usabilità
    
dlgOpen.CheckPathExists = true;
    dlgOpen.AddExtension = 
true;
    dlgOpen.Filter = "Files XML|*.xml";

    
if (dlgOpen.ShowDialog() == DialogResult.OK)
    {
        
// Istanzio un secondo dataset con i dati letti
        // dal file che 'utente ha scelto
        
DataSet dsFile = new DataSet();
        dsFile.ReadXml(dlgOpen.FileName);
        
// Unisco i due dataset (metodo Merge)
        // dsScreen.Merge(dsFile);
        // o meglio, unisco solo la Tables(0)
        
dsScreen.Merge(dsFile.Tables[0]);

        
// Popolo la ListBox con il dataset dsScreen
        // che contiene i dati uniti e mergiati assieme
        
this.lstResults.Items.Clear();
        
for(int i=0; i < dsScreen.Tables[0].Rows.Count; i++)
        {
            DataRow dr = dsScreen.Tables[0].Rows[i];
            Age ageTemp = 
new Age(Convert.ToString(dr["Name"]), Convert.ToDateTime(dr["BirthDate"]));
            
this.lstResults.Items.Add(ageTemp);
        }
    }
}

Vediamo di vedere il codice che, qualcuno se ne accorgerà, in parte riprende il discorso appena fatto sul caricamento. Innanzitutto ho bisogno di due DataSet: dsScreen e dsFile. Il primo contiene i dati contenuti nella ListBox, il secondo contiene i dati letti dal file XML. Di fatto, il primo lo posso istanziare e popolare fin da subito, ed in effetti è quello che ho fatto. Chiamo il metodo .Add sulla collection Tables, passando come parametro la famigerata getSaveTable. Il primo DataSet è pronto.

Per istanziare il secondo (che è quello che devo unire), devo usare ancora la classe OpenFileDialog come abbiamo fatto prima. L'utente sceglie il file che vuole importare prelevandolo da disco: in questo modo, istanzio dsFile chiamando il suo metodo ReadXML. Il secondo DataSet è pronto.

Adesso non mi resta da fare che accodare le DataRow di uno con le DataRow dell'altro, giusto? Sì, è giusto, ma il framework ci dà una mano. La classe DataSet espone un metodo Merge che unisce un DataSet con un altro, ed in effetti è proprio quello di cui abbiamo bisogno.

dsScreen.Merge(dsFile.Tables[0]);

A questo punto, il DataSet dsScreen contiene i dati uniti, per cui possiamo semplicemente fare il ciclo for...next visto prima e ripopolare la ListBox daccapo.

Dal punto di vista pratico, io apro l'applicazione Age, carico il file CompleanniAmiciIgor.xml: se abbiamo fatto tutto bene, la ListBox si popola con i compleanni che avevo inserito. Poi importo: seleziono il file CompleanniAmiciOmar.xml e come per magia la ListBox contiene i compleanni di tutti e due.

Conclusioni
Sui DataSet ovviamente c'è ancora molto da dire (e chissà quante cose ancora non conosco neppure io, non fatemi pensare!!): magari parlando del databinding o di qualche altro tema che verrà fuori, avrò modo di sviscerare qualcosa che oggi non ho preso in considerazione.
Piccola annotazione: se state leggendo, ricordatevi che io sto studiando per diventare MCAD, non sono certo un guru, per cui, se lo ritenete opportuno, commentati, correggetemi, criticatemi.........

powered by IMHO 1.2

Print | posted on martedì 2 agosto 2005 21:10 | Filed Under [ MCAD ]

Feedback

Gravatar

# [MCAD.22] Un nuovo Windows Form per lavorare con i database, pronti con ADO.NET

24/08/2005 18:17 | Technology Experience
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET