Gambas-it

Gambas3 => Programmazione => Topic aperto da: perseo - 25 Novembre 2010, 19:52:29

Titolo: Ciclo sui Controls di un Container
Inserito da: perseo - 25 Novembre 2010, 19:52:29
Ciao a tutti,
avrei bisogno di un aiuto.

E' possibile eseguire un ciclo per avere tutti i Control che sono dentro un container (e dentro i sub-container).
Ho dei controlli "TextBox" e "TextArea" che vorrei ripulire ed ho pensato di far eseguire un ciclo del Panel che voglio ripulire anziché scrivere il codice riga per riga.

Milio mi dette un ottimo suggerimento...

Codice: vb.net [Seleziona]
Public Sub pulisci(frm As Form, Optional salta As String)
Dim txt As Control
  For Each txt In frm.Controls
    If (Object.Class(txt).Name) = "TextBox" Or (Object.Class(txt).Name) = "TextArea" Or (Object.Class(txt).Name) = "TextPro" Then
      Object.SetProperty(txt, "Text", Null)
    Endif
  Next
End


Questo ciclo mi restituisce tutti i controlli che sono nel Form...
Però mi sto accorgendo che se fosse possibile a me interesserebbe pulire solo i Controlli di un panel (e dei relativi panel_discendenti).
Ho provato ad inserire la condizionale...

If txt.Parent.Name = nome_del_panel_che_m'interessa Then...

...però così mi esclude tutti i controlli dei sotto_panel annidati. Io invece vorrei il ciclo sul panel_genitore e su tutti i suoi panel_discendenti.

Potreste aiutarmi?  :)
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 25 Novembre 2010, 20:27:32
Per il momento sto usando questa Sub...

Codice: vb.net [Seleziona]
Public Sub pulisci(contenitore As Container, Optional salta As String)
Dim txt As Control
  For Each txt In contenitore.Children
    Select Case Object.Class(txt).Name
      Case "TextBox", "TextPro", "TextArea", "SearchBox", "SearchPro"
        Print "Puliti: " & txt.Name & " --> " & txt.Parent.Name
        If txt.name <> salta Then Object.SetProperty(txt, "Text", Null)
    End Select
  Next
End


Come vi dicevo il problema è che quando necessito di ripulire i campi di testo devo richiamarla per ogni container; ma poiché i container_figli sono esclusi... devo chiamarla anche per ogni container_figlio...

Attendo i vostri suggerimenti...  :)

PS. il comando PRINT mi ha aiutato a capire fossero i Controls ed i relativi Containers interessati nel ciclo...
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: Picavbg - 25 Novembre 2010, 22:46:14
Scusa la mia curiosità, ma non ho capito perché vuoi generalizzare la ricerca degli oggetti interni ad una form con tutti i suoi figli.
Quando si presenta la necessità di fare pulizia dovresti trovarti nella Formx.class interessata, per cui dovresti sapere già quali sono gli oggetti che essa contiene; di conseguenza, anche quanti e quali pannelli la suddetta Formx contenga.
Vuoi forse creare una classe dinamica da richiamare per fare pulizia? Quando la richiami passale un array coi nomi ed i tipi degli oggetti da svuotare, cosicché la funzione richiamata possa uttilizzarli per svolgere il suo compito. ;)
Ciao.
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 26 Novembre 2010, 00:42:55
Il discorso è duplice:

1) nel mio gestionale ho diverse Forms con tanti Controls per l'input di dati, di testo. Quindi anziché fare la solita lista di pulizia di ogni controllo, uno per uno, volevo risolvere la questione creando una routine che "ripulisse", genericamente, solo quelli dentro i Containers che interessano a me.

2) a scopo didattico, per capire e prendere dimestichezza con il codice di programmazione.

Ho notato che il tempo di pulizia è decisamente superiore rispetto alla classica lista di .Text = "", perché con questo mio approccio l'eseguibile deve fare, oltre all'operazione di pulizia, anche quella di ciclo e ricerca dei Controls che m'interessano... però al momento mi soddisfa molto. Con queste 10 righe di codice, messe in un modulo pubblico, pulisco tutte le .Text del mio progetto che m'interessano.

Non ho capito bene il discorso della classe dinamica e dell'array, tieni conto che ho ricominciato a programmare da poco più di un mese (dopo diversi anni, ma anche allora molto sommariamente).
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: fsurfing - 26 Novembre 2010, 22:12:46
potresti fare un ciclo tra i cildren del container passando alla funzione il container come parametro(oggetto)
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 26 Novembre 2010, 23:15:43
Perdonami fsurfing,
ma non ho capito molto il suggerimento che mi hai dato.  ???

A volte i container con le textbox sono annidati due o tre livelli sotto il principale.
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: fsurfing - 26 Novembre 2010, 23:17:54
certo che ti perdono del resto io non mi capisco mai quando scrivo!, purtroppo sono troppo stanco per farti un esempio ben fatto, ci penso in futuro  :)
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 27 Novembre 2010, 12:06:41
Ok!  :ok:
I'm tuned.  :)
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: fsurfing - 27 Novembre 2010, 15:47:55
eccolo qui.

l' esempio considera solo textbox, ma naturalmente lo puoi modificare facilmente in modo da pulire eventuali searchbox,valuebox ecc ecc
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 27 Novembre 2010, 21:27:03
Grazie fsurfing,

ma questo codice fa quello che fa anche il mio (anche se usa un approccio differente, che sperimenterò sicuramente: tu individui la textbox dal nome (quindi le textbox devono chiamarsi tutte textbox_qualcosa... mentre nel mio uso direttamente il nome della classe, quindi non devono avere nomi obbligati).
In pratica questo codice pulisce tutte le textbox che si trovano nel container dichiarato.
Io invece volevo che il container su cui richiami la routine, pulisca le sue textbox e tutte le altre textbox dei container in esso annidati (senza sapere quali siano), ma non quelle dei container superiori.

Seguendo il tuo progetto di esempio io vorrei che cliccando sul "pulisci" del container padre si puliscano tutte le textbox (anche quelle dei figli, e dei nipoti, ecc.  ;D ), mentre cliccando il "pulisci" del container più interno (il nipote, l'ultimo in ordine di annidamento) si puliscano solo le sue textbox. Mentre se clicco sul "pulisci" del figlio si puliscono le sue e quelle del nipote, ma non del padre...
Ora, su una famiglia con tante discendenze... come si fa?

PS. alla fine mi sono rassegnato a lanciare la routine di pulizia per ogni container di ogni form (che al massimo sono 2 o 3)... però rimane la curiosità di sapere come si può risolvere questo quesito.  :)
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: milio - 27 Novembre 2010, 21:50:34
Prova con questo, che non e' altro che una modifica al codice di fsurfing


Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 27 Novembre 2010, 21:59:23
Milio,

questo codice pulisce tutte le textbox in tutti i panel, senza considerare gli annidamenti. In pratica pulisce tutte le textbox del form.
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: milio - 27 Novembre 2010, 22:05:44
Ok come al solito non avevo capito... allora ti suggerisco di 'giocare' sui nomi dei Panel nei quali vuoi agire sulle textbox...

Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 27 Novembre 2010, 23:01:50
E' una soluzione ma non mi piace. Se chiamo l'ultimo ed il penultimo xpanel, ma poi mi trovassi nella situazione di voler pulire solo l'ultimo... dovrei rinominare i panel...

La mia domanda era anche didattica per capire questa cosa.

Ho sempre saputo che il Form può essere inteso come un contenitore grosso... che contiene tutti gli oggetti che vi sono dentro. Se uso la pulizia sul Form pulisce qualsiasi cosa (compresi tutti i container in esso annidato); mentre se provo sui container questo non è possibile (cioè non è possibile risalire a tutta la discendenza). Perché?

Questo era il codice di pulizia delle textbox dell'intero form:

Codice: vb.net [Seleziona]
Public Sub pulizia(Optional salta As String)
Dim txt As Control
  For Each txt In Me.Controls
    If (Object.Class(txt).Name) = "TextBox" Or (Object.Class(txt).Name) = "TextArea" Then
      If txt.name <> salta Then Object.SetProperty(txt, "Text", Null)
    Endif
  Next
End


La mia curiosità è di sapere perché la classe "container" è priva della proprietà .Controls... (quella che nell'esempio fa fare il ciclo for each)
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: milio - 27 Novembre 2010, 23:22:43
Io purtroppo non ti so rispondere.  :-[

Pero' che senso ha se prima vuoi eliminare tutti i dati contenuti nelle textbox di tutti i panel e poi solo in alcuni...  :-\
Dovrai, ad ogni modo, fare dei controlli su quali panel devono essere coinvolti, quindi o con il nome del contenitore o con qualsiasi altro metodo dovrai comunque far capire a gambas su quale panel agire...

Non credo che ci sia una soluzione che si adatti a quello che stai pensando di fare, senza scrivere delle regole per un eventuale ricerca degli oggetti.


Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 27 Novembre 2010, 23:52:10
Pero' che senso ha se prima vuoi eliminare tutti i dati contenuti nelle textbox di tutti i panel e poi solo in alcuni...  :-\

In effetti milio come necessità può apparire abbastanza insolita... Ti racconto come sono arrivato a tale richiesta.

Nel mio progetto ho messo in una delle form un toolpanel, e nella prima tool del toolpanel ci sono una serie di textbox per l'inserimento del nome, cognome, cod.fiscale, data nascita, ecc. ecc. Fin lì la routine pulizia funzionava a meraviglia...
Poi quando ho disegnato le textbox che sono nel secondo tool del toolpanel ho notato che quando cancellavo il contenuto di quelle del primo, automaticamente (anche se erano nascoste nel secondo) pulivo anche quelle del secondo.
Da qui la necessità di fare la pulizia in un container e non nel form intero. Pensavo che il container principale ereditasse tutti i controlli anche dei container figli... ma non essendoci una proprietà .controls, come dici tu, bisogna giostrare con i nomi o con qualcosa di simile...
Alla fine la cosa più semplice è chiamare la pulizia dei panel che m'interessano (uno per uno, tanto sono pochi). Però rimane la curiosità di sapere come si potrebbe risolvere questa situazione, e perché i container non hanno una proprietà .Controls. :)
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: Picavbg - 28 Novembre 2010, 23:04:23
Il discorso è duplice:

1) nel mio gestionale ho diverse Forms con tanti Controls per l'input di dati, di testo. Quindi anziché fare la solita lista di pulizia di ogni controllo, uno per uno, volevo risolvere la questione creando una routine che "ripulisse", genericamente, solo quelli dentro i Containers che interessano a me.

2) a scopo didattico, per capire e prendere dimestichezza con il codice di programmazione.

Ho notato che il tempo di pulizia è decisamente superiore rispetto alla classica lista di .Text = "", perché con questo mio approccio l'eseguibile deve fare, oltre all'operazione di pulizia, anche quella di ciclo e ricerca dei Controls che m'interessano... però al momento mi soddisfa molto. Con queste 10 righe di codice, messe in un modulo pubblico, pulisco tutte le .Text del mio progetto che m'interessano.

Non ho capito bene il discorso della classe dinamica e dell'array, tieni conto che ho ricominciato a programmare da poco più di un mese (dopo diversi anni, ma anche allora molto sommariamente).
$Array[0]= TextBox1.Name
$Array[1]= Panel1.Name
$Array[2]= TextBox2.Name

Scusa se rispondo solo adesso, ma per me questo é un periodo nel quale dedico il mio tempo ad altro e non posso concentarmi molto su Gambas. Infatti soffre pure il mio programma che é messo letteralmente in deposito. A te sembra difficile lo studio dell'utilizzo di una classe esterna a cui passare i parametri necessari per la pulizia degli oggetti che ti interessano, ma mi pare che l'affannosa ricerca di di una soluzione attraverso la realizzazione di una funzione universale che agisca come vuoi tu sia ancora più complessa del metodo che ti ho suggerito più sopra.

 Provo a farti un esempio veloce su quello che voglio dire:
Codice: gambas [Seleziona]
PUBLIC SUB Qualsiasi()
DIM $Array AS NEW String[]
DIM Classe1 AS ClasseDinamica
-------------- bla bla bla -------------
-------------- bla bla bla -------------
$Array[0]= TextBox1.Name
$Array[1]= TextBox2.Name      'oggetto figlio di Panel1
$Array[2]= ComboBox1.Name    'oggetto figlio di Panel1
Classe1 = NEW ClasseDinamica($Array)
-------------- bla bla bla -------------
-------------- bla bla bla -------------
END
PUBLIC SUB _new($ParametriArray AS NEW String[])         'Metodo _new della "ClasseDinamica"
DIM i AS Integer
DIM Conta AS Integer
Conta = $ParametriArray.Count - 1
For i = 0 to Conta
 $ParametriArray.Text=""
Next
END


Ho buttato giù la mia idea in codice. Non so se funziona perché non l'ho provata. Puoi farlo tu se ti pare interessante.
Comunque vada, buon lavoro. :D
Ciao
Titolo: Re: Ciclo sui Controls di un Container
Inserito da: perseo - 29 Novembre 2010, 02:45:30
Grazie mille Picavbg!

Appena ho un attimo di tempo lo provo... Purtroppo il tempo è quello che è, visto che per realizzare questo progetto faccio le ore piccole, ma poi devo alzarmi comunque alle 7.  :rolleyes: