La quasi totalità dei software offre all'utente la possibilità di configurare una gran varietà di aspetti dell'applicazione, a partire da impostazioni grafiche o estetiche fino ad arrivare a parametri essenziali per il suo corretto funzionamento (percorsi file, cartelle da utilizzare, ecc.).
Molti sviluppatori normalmente preferiscono gestire in proprio questo aspetto, utilizzando diverse tecniche per assicurare la persistenza dei parametri impostati. Un primo approccio è quello basato su database; è sufficiente preparare una semplice tabella che contenga delle coppie chiave-valore da cui recuperare dati con una veloce interrogazione. Questo approccio ha però un grave inconveniente: la stringa connessione deve essere conosciuta a priori e preferibilmente non deve essere tra i parametri.
Una seconda soluzione è quella di serializzare o comunque salvare su file le coppie chiave-valore. In questo caso il linguaggio
XML si presta in modo eccellente allo scopo, permettendo di creare agilmente gerarchie, di dati, gruppi e così via. Questo complica un po' la vita dello sviluppatore: se da una parte le librerie .NET offrono un ottimo supporto per la manipolazione di file
XML, dall'altra la tentazione (o la necessità) di creare gestori personalizzati per le impostazioni è spesso molto grande.
Fortunatamente a disposizione degli sviluppatori .NET esiste una risorsa spesso non sfruttata a dovere: gli
Application Settings.
Questi oggetti permettono di serializzare i parametri che preferiamo in un file
XML in modo semplice e diretto. Immaginiamo ad esempio di voler salvare le dimensioni di default di una Form e di voler permettere all'utente di personalizzare i valori di altezza e larghezza (in pixel).
Creiamo una nuova
Solution e diamo doppio clic sul file
Settings.settings per accedere al comodo editor delle impostazioni.
Da questo pannello è possibile creare agilmente i nuovi parametri, specificandone il nome, il tipo, l'ambito di accesso (Scope), e un valore iniziale. Lo []Scope di ogni parametro può essere di tipo
Application o di tipo
User. Il primo crea un setting valido a livello di applicazione, e l'utente non può modificarlo a runtime; caso tipico di utilizzo di setting con scope
Application sono ad esempio l'inserimento di
ConnectionString. Il tipo
User invece permette di definire preferenze che l'utente può manipolare come preferisce.
Inseriamo quindi i due parametri interi con scope User che utilizzeremo nella nostra applicazione d'esempio, chiamati rispettivamente
DefaultFormHeight e
DefaultFormWidth:
Nella form principale, creiamo dunque un metodo, chiamato
ResizeFromSettings(), che preleverà i valori dei due parametri serializzati e ridimensionerà di conseguenza la finestra. Questo metodo dovrà essere chiamato ad ogni avvio della form (evento
Load) e ogni volta che l'utente cambierà le impostazioni.
private void ResizeFromSettings()
{
//retrieve user settings
int formHeight = AppSettingSample.Properties.Settings.Default.DefaultFormHeight;
int formWidth = AppSettingSample.Properties.Settings.Default.DefaultFormWidth;
//set the new form size
this.Size = new Size(formWidth, formHeight);
}
Come è possibile vedere dallo spezzone di codice, l'accesso ai due parametri creati in precedenza è diretto ed estremamente semplice. Aggiungiamo inoltre un pulsante che servirà per lanciare una
FormDialog per la configurazione dei parametri.
Creiamo ora la semplice form che utilizzeremo per dare la possibilità all'utente di cambiare il valore dei parametri. Questa form banalmente potrebbe contenere semplicemente due
Label e due
TextBox (un componente per ogni setting) e due
Button (uno per salvare e l'altro per annullare le modifiche). Nell'esempio allegato ho preferito utilizzare invece due
TrackBar per l'input dei valori, essenzialmente perché questo componente ci consente di evitare di effettuare la validazione dei parametri, permettendoci di:
- Definire un valore minimo di altezza/larghezza per la finestra (ad esempio 100 px)
- Definire un valore massimo di altezza/larghezza per la finestra (la massima dimensione dello schermo)
- Visualizzare facilmente il valore corrente
- Essere assolutamente certi che l’input inserito sarà un valore intero (la proprietà
Value di un oggetto
TrackBar è sempre un intero)
- Fornire un controllo più gradevole e usabile rispetto ad un classica casella di testo
Nel codice d'esempio ho inoltre inserito un pulsante extra che serve a riportare i parametri al loro valore iniziale (che potremmo chiamare il
Factory Default), e alcune meccanizzazioni gradevoli (il pulsante di salvataggio che si abilita solo se una slide viene spostata, due etichette che visualizzano il valore delle
TrackBar, ...)
Alla pressione del tasto di salvataggio (evento
Click), sarà sufficiente prelevare i valori inseriti nelle
TrackBar, lanciare l'opportuno metodo
Save() dei parametri e impostare a OK il risultato della
Form Dialog.
private void saveButton_Click(object sender, EventArgs e)
{
//update settings with selected values
AppSettingSample.Properties.Settings.Default.DefaultFormWidth = this.widthTrackBar.Value;
AppSettingSample.Properties.Settings.Default.DefaultFormHeight = this.heightTrackBar.Value;
AppSettingSample.Properties.Settings.Default.Save();
//close the dialog form with OK result
this.DialogResult = DialogResult.OK;
}
Qualora l'utente invece voglia annullare l'operazione corrente (tramite il relativo pulsante) basterà impostare a
Cancel il risultato della
Form Dialog.
Se i parametri sono stati modificati, la form principale viene ridimensionata di conseguenza.
Chiudendo e riavviando il programma, noterete che le impostazioni sono state mantenute, grazie alla serializzazione dei parametri sul file
nomeprogramma.config.
<userSettings>
<AppSettingSample.Properties.Settings>
<setting name="DefaultFormHeight" serializeAs="String">
<value>300</value>
</setting>
<setting name="DefaultFormWidth" serializeAs="String">
<value>300</value>
</setting>
</AppSettingSample.Properties.Settings>
</userSettings>