|
I control della JBCL utilizzano i
dataset per l’accesso ai dati. I dataset rappresentano il
“modello”, mentre i Control sono delle “viste”
su questo modello, che possono manipolarlo. I control e i dataset,
per essere collegati, si devono trovare nella stessa classe. Se
questa condizione viene soddisfatta, per tutti i control data aware
può essere impostata ,tramite l’Object Inspector, la
proprietà dataset che lega il control ai dati di uno
specifico dataset.
Nella JBCL ci sono vari tipi di
dataset, diversi tra di loro per sia per la fonte dati (un database
SQL o un file) che per la modalità di accesso alla fonte dati
(nel caso dell’SQL, accesso tramite Query o tramite Stored
Procedure). Nel caso di dataset relativo ad un database (per esempio
il QueryDataSet), per collegarlo ad un database occorre un
componente di tipo Database che deve appartenere alla stessa
classe del dataset. La personalizzazione del Database richiede
che si specifichi l’URL JDBC del database da accedere (per
esempio jdbc:odbc:agenda). Ancora, per utilizzare il dataset
possono essere necessari dei componenti “resolver” che
hanno lo scopo di guidare l’aggiornamento del database.
In generale dunque per gestire
l’accesso ai dati occorrono diversi
componenti. Spesso questi componenti sono gli stessi per form
diverse; poiché i componenti devono appartenere alla stessa
classe, questo porta a ripetere parti anche consistenti di codice. È
evidente l’esigenza di poter di “raccogliere” i
vari componenti di accesso a dati sia per semplificare il riuso, sia
per isolare la “business logic” e separarla dalla
gestione dell’interfaccia utente. JBuilder supporta la nozione
di DataModule, che consente di centralizzare la gestione
dell’accesso a dati. Come i componenti di gestione dati sono
analoghi ai componenti visuali ma non mostrano alcuna interfaccia
utente, allo stesso modo un datamodule è analogo ad una form,
ma non mostra alcun elemento grafico. Si costruisce un datamodule
attivando il Wizard apposito dal menù File|New. Il
wizard crea una nuova classe (per esempio DataModule1) che
implementa l’interfaccia DataModule e genera il codice
che permette di avere una sola istanza del datamodule condiviso tra
le varie form che lo utilizzano. Al datamodule è possibile
aggiungere e personalizzare tutti i componenti di gestione dati
necessari. Una volta completato, inserendo il datamodule come campo
in una form, tutti i componenti di gestione dati in esso contenuti
(database, dataset, resolver) sono accessibili. Per inserire il
datamodule in una occorre aggiungere (a mano) la seguente riga di
codice:
DataModule1
datamodule1 = DataModule1.getDataModule();
Attenzione: ho notato che se il
datamodule non è compilato non si riesce ad utilizzarlo:
quindi occorre dare un rebuild prima di utilizzarlo. Notare
anche che il codice non crea una nuova istanza: questa viene creata
una volta sola, e getDataModule() ritorna la stessa per tutte
le form. Una volta inserito il datamodule in una form, è
possibile utilizzare tutti i componenti del datamodule, come se
fossero stati inseriti direttamente nella form: per esempio, l’Object
Inspector presenta, come opzioni per la proprietà dataset,
tutti i dataset contenuti nel datamodule.
Vediamo adesso di capire meglio l’uso
dei dataset.Un dataset è essenzialmente una tabella dati,
composta da record (rows) suddise in campi (column);
occorre tenere presente che ogni dataset ha un cursore interno che
punta ad un record “corrente”. I control hanno capacità
di visualizzazione di un dataset differenti. Il più generale è
il GridControl che visualizza l’intera tabella, e mostra
evidenziata la riga dove si trova il cursore; questo control richiede
che si specifichi solo la proprietà dataset per il
collegamento. Un ListControl invece è in grado di
visualizzare una intera colonna, ovvero il valore di un campo per
tutte le righe di un dataset, mostrando evidenziato il valore della
riga dove si trova il cursore: le proprietà che occorre per il
collegamento specificare sono sia dataset che column.
Infine ci sono la maggior parte dei control, che hanno una capacità
di visualizzazione più limitata, come il FieldControl o
il LabelControl. Questi sono in grado di visualizzare soltanto
un valore, e precisamente il valore della columns specificata
della riga corrente del dataset (e ovviamente per essi occorre
impostare entrambe le proprietà).
È importante notare che i vari
control sono “sincronizzati” col dataset: ovvero, se si
interagisce con un control, questo modifica lo stato del dataset,
modifica che poi si ripercuote su tutti gli altri Control collegati a
quel dataset. Per esempio supponiamo di avere un ListControl e
un FieldControl collegati alla stessa colonna dello stesso
dataset. Il ListControl mostra tutti i dati della colonna
mentre il FieldControl il valore della riga corrente della
colonna. Modificando il dato specificato nel FieldControl,
vedrò che il ListControl cambia di conseguenza.
Analogamente, cliccando e selezionando un nuovo elemento nel
ListControl cambio la riga corrente del dataset, e di
conseguenza cambia il valore mostrato nel FieldControl. Ci
sono anche componenti che, pur non essendo delle viste, consentono
ugualmente di interagire con il dataset. Per esempio la StatusBar
se collegata ad un dataset mostra informazioni come la posizione
corrente o messaggi di errore su operazioni sul dataset. Oppure il
NavigatorControl, che mostra una bottoniera standard per la
navigazione in un dataset, e che collegata ad un dataset consente la
navigazione in esso.
Esaminiamo infine la gestione delle
colonne. In generale notiamo che, quando viene collegato un dataset
ad un database, e un control ad un dataset, l’editor visuale
mostra in modalità design “live data”, ovvero il
risultato reale dell’interrogazione al dataset. Tra le altre
cose visualizzate dall’IDE, ci sono le column contenute in un
dataset. In Figura 5 possiamo vedere l’albero dei
componenti di un datamodule: per il dataset sono visualizzati come
suoi figli le colonne dati risultanti dall’esecuzione della
query. Le colonne visualizzate sono però “transienti”,
ovvero mostrano i dati estratti dalla query, ma non corrispondono a
componenti realmente inseriti nel programma. Tuttavia, non appena si
modificano le proprietà di una colonna, queste diventano
“persistente”. Cioé viene generato codice per la
gestione di una colonna: se si esamina il codice si vede che viene
costruito un oggetto Column corrispondente, e nella
visualizzazione dell’albero dei componenti il nome della
colonna viene posto tra parentesi quadre.
È importante capire che quando
si collega un control ad una colonna di un dataset (che sia un
FieldControl, un ListControl, un GridControl o altro), le
proprietà di visualizzazione del dato vengono impostate
nella colonna. Tra le impostazioni che si possono specificare
citiamo la precisione, il colore dello sfondo, se è visibile
(in un GridControl) o meno eccetera. Particolarmente utile è
la gestione delle maschere. Utilizzando dei pattern, è
possibile sia formattare l’output che controllare l’input.
Per esempio, utilizzando la maschera d/MM/yy nella proprietà
displayMask si visualizza la data nel formato numerico
giorno/mese/anno, mentre impostando la stessa stringa come
editMask, viene accettato soltanto un input nel formato di
prima. Le maschere vengono usate da molti controlli ma non da tutti.
Per esempio, se si vogliono usare le maschere, occorre fare
attenzione a confondere un TextFieldControl (che ignora le maschere)
con FieldControl (che invece le usa).
|