Traduzione in Italiano di Antonio Campagna - prima traduzione Agosto 1999 - rev. giugno 2001

Come lavorare con schede 
a pagine multiple

in Visual dBASE 7.x

Ken Mayer, dBVIPS

Lo scopo di questo documento è discutere delle schede a pagine multiple ed il loro uso. Pur essendo un argomento abbastanza semplice ad un neofita di Visual dBASE può creare un po’ di confusione.


Cos'è una scheda multi pagina Cambiare pagine con i Tabbox

Convalida

Codice esempio
Concetti base Cambiare pagine con i Pulsanti Sommario  

Cos’e' una scheda a pagina multipla?

E’ una singola scheda in cui i dati (informazioni) sono disposti in più pagine (di fatto non ci sono pagine o oggetti pagina da gestire N.d.T.). Nel mondo dBASE/DOS questo è stato realizzato con schede multiple. In Visual dBASE questo può essere fatto con una scheda. (anche se non è una buona idea creare una scheda di 10 pagine in Visual dBASE, questo porta inevitabilmente all'esaurimento delle risorse di Windows.)

Ci sono almeno tre metodi che possono essere usati per creare e lavorare con schede a pagina multipla:

Questo documento tratterà i primi due metodi. Non parleremo dell'utilizzo dell'oggetto Notebook, che è un controllo visuale che può essere usato in aggiunta alle discussioni qui mostrate di un oggetto container a pagine multiple (non di una scheda). 
Non lasciare che questo documento limiti la tua immaginazione. Visual dBASE è un potente strumento di sviluppo che offre notevoli possibilità di raggiungere l’obiettivo in modi diversi, rispetto a quelli discussi in questo documento.

Alcuni concetti di base

Le schede e gli oggetti di Visual dBASE hanno una proprietà che non esisteva in dBASE 5.0 per Windows o nei prodotti dBASE/DOS: PageNo.
Questa proprietà è vitale per il compito che dobbiamo affrontare.
La proprietà PageNo riferita ad una scheda indica il numero della pagina attiva. Questo per esempio, può essere cambiato da programma con l'istruzione:

form.PageNo := 2

Gli oggetti hanno una proprietà PageNo che indica la pagina sulla quale appariranno. Ad esempio, un entryfield che è stato assegnato alla pagina 2, avrà la sua proprietà pageNo definita dalle seguenti linee:

class ENTRYFIELD1(parentObj, name) of  ENTRYFIELD(parentObj, name)

  with (this)
     height = 1
     left = 1.2857
     top = 0.7273
     width = 10.7143
     metric = 0 // Caratteri
     pageno = 2
  endwith
endclass

Importante: Poiché la pagina di default di qualsiasi scheda è pagina 1, qualunque oggetto sarà messo su pagina 1. Normalmente non "riverseremo fuori" la proprietà pageNo riferita a pagina 1.
La proprietà PageNo può essere utilizzata come ogni altra proprietà. Comunque, nella maggior parte casi puoi lasciare un oggetto specifico su una pagina specifica.
In alcuni casi si può volere che un oggetto appaia su tutte le pagine di una scheda. Questo risulta tanto facile quanto il resto, se impostiamo la proprietà PageNo a 0 (zero), l’oggetto apparirà su tutte le pagine della scheda.

Metodo 1 - Cambiare pagine con TabBox

Quando la scheda é in esecuzione l'utente dovrà avere la possibilità di spostarsi da una pagina all'altra.
Il controllo TabBox di Visual dBASE è progettato per permetterci di creare ed utilizzare facilmente schede a pagine multiple.
NOTA: Il controllo Tabbox non si limita a lavorare con schede che hanno più pagine. E' possibile avere controlli Tabbox multipli sulla stessa scheda, con associato vario codice per fare altre cose... Ancora una volta, Visual dBASE è un potente pacchetto linguaggio/software e se si può immaginare un "uso" per il controllo Tabbox, ci sono notevoli possibilità di realizzare ciò che abbiamo immaginato...

In modalità progettazione nella pagina "Standard" della "Tavolozza Componenti", troverai un'icona per il TabBox:

 

Se clicchiamo sul componente Tabbox e lo trasciniamo su una scheda, un singolo "separatore" sarà messo sul fondo della scheda.

Il TabBox per default dovrebbe impostare a 0 (zero) la sua proprietà PageNo. Se cosi non fosse impostiamola adesso. Se vogliamo possiamo assegnare un nome al TabBox, l'impostazione predefinita è di solito TabBox1 ed è quello che questo documento presumerà. Ovviamente se ne abbiamo bisogno possiamo impostare i nomi per i separatori. Se guardiamo nella proprietà DataSource, dovremmo vedere:

ARRAY {"TabBox1"}.

Questo porta ad un argomento interessante che esamineremo brevemente (gli array sono trattati con maggiori dettagli in altri documenti HOW TO): 

Array letterali

Il tipo array predefinito per un TabBox è chiamato "Array letterale". Questo array può essere definito con il disegnatore visuale. Una cosa circa questo tipo di array che un po’ sconcerta è che non ha un nome. Non esiste modo per riferirsi al suo contenuto. Nella maggior parte dei casi quando usiamo un TabBox, esso é assolutamente eccellente! Comunque, non dobbiamo usare un array letterale se non lo vogliamo. Possiamo usare invece un array standard di Visual dBASE (uno con un nome), la sola ragione che mi viene in mente circa il fatto che si vuole usare un array standard é se si ha bisogno di conoscere il testo del separatore dove attualmente si trova il cursore, ma ci potrebbero essere facilmente altre ragioni...

I disegnatori visuali ci permettono di costruire il nostro array attraverso una "finestra di dialogo" davvero elegante. Per visualizzare questa "finestra" tramite il modulo "Ispezione" clicchiamo sul pulsante della proprietà datasource del tabbox,

compare una finestra di dialogo con la definizione dell'array corrente


 

clicchiamo sul pulsante ed apparirà la finestra di dialogo "Genera array" 

Possiamo aggiungere, rimuovere e riordinare le "etichette" dei separatori piuttosto facilmente con questa finestra di dialogo e quando abbiamo finito il pulsante "OK" metterà i contenuti dell'array sulla scheda. Il numero di separatori (tabs) sul tuo tabbox corrisponde al numero di elementi nell'array.

L'evento OnSelChange

In Ispezione (selezionando il tabbox) se clicchiamo sulla pagina degli eventi, si vedrà questo evento. Clicchiamoci su. Possiamo aggiungere del codice per essere eseguito con un codeblock, o possiamo impostare qualcosa di più sofisticato (una funzione). Io raccomando di impostare qualcosa di più sofisticato, tramite una procedura. Questo è facilmente realizzabile tramite un semplice clic sul pulsante   nel modulo "ispezione" relativo a questo evento. Impostazione scheda attiverà l'editor di sorgenti e metterà un'intestazione per l'evento e subito dopo potremo inserire il nostro codice:

PROCEDURE Tabbox1_onSelChange

In questa procedura si può impostare il "PageNo" della scheda con il corrente numero di separatore (elemento). La proprietà che da il numero del separatore corrente è: CurSel.

La procedura potrebbe somigliare:

PROCEDURE Tabbox1_onSelChange
        form.PageNo := this.CurSel

La ragione per mettere questa istruzione nel codice che gestisce l'evento è che vogliamo ottenere  qualcosa di più sofisticato (ad esempio: effettuare un controllo per vedere quale pagina si é adesso,  impostare specifici valori per gli oggetti sulla scheda, cambiare il rowset della scheda , molte altre possibilità saltano in mente...).

Metodo 2 – Cambiare pagine con i pulsanti

Mentre la maggior parte delle nuove applicazioni usa i TabBoxes per cambiare pagina, un altro metodo piuttosto efficace è usare i pulsanti. Se mettiamo un paio di pulsanti su una scheda avremo bisogno di impostare gli eventi OnClick per gestire gli spostamenti di pagina. Ciò è abbastanza semplice (esempio sotto).

Come dicevamo sopra dovremmo impostare l'evento OnClick per entrambi i pulsanti, ma prima ci sono alcune altre cose che potrebbe essere necessario fare. Si consiglia di agganciarsi ad un evento piuttosto che usare un codeblock.

Un suggerimento molto semplice é quello di agganciarsi all'evento(On_click) dei pulsanti, per gestire l’incremento e il decremento del numero di pagina e successivamente chiamare un’altra routine per gestire ciò che può essere necessario fare, quando si cambia pagina (come impostare il fuoco all’oggetto adatto sulla pagina adatta).

Il seguente codice di esempio presume che i pulsanti siano chiamati "PagSucc" e "PagPrec":

PROCEDURE PagSucc_OnClick

form.PageNo++ // incrementa il numero pagina
class::MyPageChange()
// procedura per gestire altre istruzioni necessarie

PROCEDURE PagPrec_OnClick

form.PageNo-- // decrementa il numero pagina
class::MyPageChange()
// come sopra

La descrizione dell'evento OnClick per i pulsanti sarebbe allora (nel modulo Ispezione della Proprietà onclick, pagina dei Metodi): class:: PagSucc_OnClick oppure: class::PagPrec_OnClick.

Quando navighiamo attraverso una scheda con diverse pagine, potremmo avere un problema se il codice che gestisce il pulsante non è "appropriato".

Che cosa accade se siamo su pagina 1, e l'utente clicca sul pulsante "Pagina Precedente" ?

Non esiste pagina 0 (o meglio esiste, ma di solito è abbastanza brutta perché contiene tutti gli oggetti sulla scheda).

Che cosa succede se siamo sull'ultima pagina, e l'utente clicca sul pulsante "Prossima Pagina" ?

Se non c'è nessuna pagina definita verrà visualizzata sulla scheda una pagina bianca.

Questo può essere gestito nella procedura MyPageChange abilitando o disabilitando i pulsanti:

PROCEDURE MyPageChange

if form.PageNo == 1
      form.PagPrec.Enabled := false // disabilita il pulsante
else
   form.PagPrec.Enabled := true // abilita il pulsante
endif

 if form.PageNo == 3 //si presume che pagina tre sia l'ultima
      form.PagSucc.Enabled = false // disabilita il pulsante
 else
      form.PagSucc.Enabled = true // abilita il pulsante
  endif

Queste due istruzioni if/endif possono essere raffinate un po’ usando la funzione lIF() di dBASE, ma si è voluto mostrare la versione del codice più lunga per amore di chiarezza.
Sotto c'è la versione ridotta:

form.PagPrec.Enabled := iif(form.PageNo==1,false,true)

form.PagSucc.Enabled := iif(form.PageNo==3,false,true)

SUGGERIMENTO: Per evitare di modificare il codice tutte le volte che si deve cambiare il valore che indica l'ultimo numero di pagina, si può usare il metodo della scheda pageCount() quale numero dell’ultima pagina:

form.pageCount() // numero di pagina più alto usato su una scheda

ed usarlo nel codice descritto sopra, prova:

form.PagSucc.Enabled := iif(form.PageNo==form.pageCount(),false,true)

Il vantaggio che ne traiamo risiede nel fatto che se dovessimo in un secondo tempo aggiungere/rimuovere pagine dalla scheda, non si deve aggiornare il codice che le gestisce.

La procedura MyPageChange

La procedura MyPageChange è dove "diciamo" a Visual dBASE quello che deve fare quando cambia il numero di pagina. 
Per esempio se volessimo impostare il fuoco sul primo oggetto di ciascuna pagina:

PROCEDURE MyPageChange
// se usiamo i pulsanti per muoverci tra le pagine:
  form.PagPrec.Enabled := iif(form.PageNo==1,false,true)
 form.PagSucc.Enabled := iif(form.PageNo==form.pageCount(),false,true)
// gestisce l'impostazione del fuoco e qualsiasi cosa che potrebbe essere
// necessario fare quando cambia il numero di pagina.
do case
     case form.PageNo == 1
	form.entryfield1.setfocus()  // entryfield1 ottiene il fuoco
     case form.PageNo == 2
	form.entryfield43.setfocus() // entryfield43 della pagina 2 ottiene il fuoco
     case form.PageNo == 3
	form.entryfield71.setfocus() // come sopra
endcase

CONVALIDA

Possiamo voler effettuare un processo di convalida dei nostri entryfields e degli altri oggetti collocati  su di una pagina, quando ci si sposta di pagina. Questo può essere gestito come nella procedura MyPageChange.

Il codice potrebbe verificare qualche cosa di simile:

if form.Tabbox.Cursel # 1 and empty(form.entryfield1.value)
     MsgBox('Devi inserire il codice cliente prima!') // Avviso
     This.CurSel := 1                                              // ritorna a pagina 1
     form.entryfield1.SetFocus()                             // dai il fuoco all'entryfield1
else
     form.pageno := this.cursel  // altrimenti cambia pagina
endif

Problemi potenziali

Non è probabilmente una buona idea aggiungere dati in altre tabelle su altre pagine se il "master record" sulla prima pagina non sia stato salvato. Una possibile soluzione è impedire agli utenti di cambiare pagina tramite la disabilitazione della proprietà enabled di un tabbox (o se usiamo i pulsanti per navigare, i pulsanti coinvolti) fino a che non si salvi il record. Nota che tramite gli oggetti OODML database e query di Visual dBASE 7, questo non é più un grosso problema come lo era nelle versioni precedenti di VdBASE.

In modalità progettazione, se salviamo la scheda ed il numero di pagina è diverso da 1, la prossima volta che manderemo in esecuzione la scheda, essa visualizzerà la pagina selezionata quando abbiamo eseguito il salvataggio della scheda. Per risolvere questo problema si può aggiungere il seguente codice al metodo onOpen della scheda

PROCEDURE form_onOpen

    form.Tabbox1.curSel := 1 // questo attiverà l’evento onSelChange del tabbox

// qualsiasi altro codice che hai bisogno

Sommario

Brevemente, la flessibilità di Visual dBASE è tale che si può trovare probabilmente una serie di ragioni per usare schede multi pagina. Ciò si può realizzare usando le tecniche qui mostrate, possiamo da programma spostarci su una "pagina nascosta" per visualizzare informazioni utente sotto circostanze specifiche, ecc.. come sempre, se possiamo pensare a fare qualcosa, le probabilità che puoi farlo in Visual dBASE sono notevoli.

Per assistenza specifica per favore usate il Newsgroups di Visual dBASE (vedi: http:// www.dbase2000.com per più dettagli). Per favore non contattate l'autore direttamente tramite la posta elettronica...

Copyright 1998, Kenneth J. Mayer. All rights reserved.

Codice di esempio

Nel file .ZIP ci sono due semplici schede le quali mostrano alcune delle tecniche menzionate in questo documento. Questi sono "MULTIPG1.WFM" e "MULTIPG2.WFM." Questi file contengono esempi piuttosto semplici, ma riflettono i concetti mostrati in questo documento.   

EoHT: MULTPAGE.HTM -- 11/02/1998 -- KJM