Discussione chiusa
Visualizzazione dei risultati da 1 a 4 su 4

Discussione: Accedere ai controlli di un form da un form diverso

  1. #1
    L'avatar di alextyx
    alextyx non è in linea Moderatore Globale
    Luogo
    Prato
    Post
    2,585

    Accedere ai controlli di un form da un form diverso

    Introduzione:

    Subito dopo aver postato il mio 'microlavoro' sull'accesso ai controlli di un form da un thread diverso, mi sono reso conto che forse per la maggior parte di coloro che iniziano a confrontarsi con Vb.Net, il problema principale, fonte di tante discussioni sui vari forum, è un più banale accesso ai controlli di un form dal codice di un form diverso. La domanda tipica è qualcosa del genere: "Clicco su button1 di Form1, apro Form2 e da Form2 voglio cambiare il contenuto di una textbox in Form1. Come faccio?".
    Partendo da questa esigenza, mi sono convinto a spendere un po' di tempo per quello che a molti sembrerà un argomento banale, ma che all'inizio ha creato qualche problema ai più (me compreso ).


    Applicabilità:

    Alcuni concetti di base sono validi in tutte le versioni di Vb.Net, ma il lavoro è inteso globalmente valido per VB2005 in tutte le sue versioni.


    Premessa:

    Quando più avanti si parlerà familiarmente di 'vedere' o 'condividere' un oggetto, si intenderà quello che più tecnicamente viene definito avere un riferimento all'oggetto e ci si occuperà sempre di oggetti di tipo 'reference' (la maggior parte di ciò che si usa in VB).
    Gli oggetti di tipo 'reference' vengono allocati in una speciale area di memoria detta 'Heap'. Se ad una variabile viene assegnato un oggetto esistente, non si ha una ricostruzione di un oggetto identico nella variabile (cioè nello spazio di memoria ad essa dedicato), ma semplicemente si comunica alla variabile che essa è associata a quell'oggetto. E' come se la variabile divenisse un 'puntatore' all'area di memoria in cui risiede l'oggetto. Attraverso le informazioni contenute nella variabile, sulla rilocazione dell'oggetto nell'heap, noi possiamo raggiungerlo e manipolarlo.


    VB2005 e le istanze di default:

    Probabilmente per venire incontro a chi, abituato a VB6, voleva poter avere un riferimento a un Form semplicemente scrivendone il nome, in VB2005 è stata introdotta l'istanza di default. Se avete un Form di nome Form1 e un altro di nome Form2, potete aprire Form2 da Form1, semplicemente con l'istruzione:

    Form2.Show()

    Così come dall'interno di Form2 potete cambiare il 'Text' di Form1 con questo codice:

    Form1.Text = "Visto!"


    Infatti, le istanze di default sono già state create e sono globalmente visibili.
    Però non tutti utilizzano una sola istanza di un form e inoltre se si impara a rendere visibile l'istanza non predefinita di un form, questo vale anche per una connessione, o quanto altro possiamo avere in animo di condividere nel nostro progetto.



    Dichiarazione Pubblica:

    Per rendere visibile una istanza di una determinata classe, non è strettamente necessario che questa sia 'costruita' in una zona pubblica, come ad esempio in un modulo, ma è necessario che questa sia 'dichiarata' come 'public' in un modulo, ad esempio:

    Module Module1

    Public F1 As Form1

    End Module


    La chiamata al metodo costruttore (new), può avvenire anche altrove. Rifacendosi all'esempio dei nostri Form1 e Form2, potremmo avere:

    codice:
     
    Public Class Form1
     
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    F1 = New Form1 'Qui si costruisce l'istanza F1 di Form1
    Form2.Show()
    End Sub
     
    End Class
    codice:
     
    Public Class Form2
     
    Private Sub Form2_Load(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Me.Load
    F1.Show() 'L'istanza F1 è visibile anche da qui
    End Sub
     
    End Class
    Come si può vedere, il fatto di avere dichiarato l'istanza F1 come pubblica in un modulo, mi consente di poterla prima costruire in Form1 e poi maneggiare in Form2. Essa risulta infatti visibile ad entrambi (cioè entrambi i Form possono avere un riferimento all'istanza F1). Ovviamente, prima un'istanza va costruita (new) e solo dopo ci si può lavorare.


    Costruzione Pubblica:

    Volendo si può optare anche per la costruzione pubblica dell'istanza, tuttavia, anche se l'istanza verrà creata la prima volta che verrà 'riferita', qualora venisse distrutta, essa andrà comunque ricostruita esplicitamente, quindi questo metodo è consigliabile solo se si prevede di non distruggere l'istanza fino al termine dell'applicazione.

    codice:
     
    Module Module1
     
    Public F1 As New Form1
     
    End Module

    Passaggio di un riferimento tra Form:

    Supponiamo che da Form1, o da un altro Form della mia applicazione, io voglia aprire Form2 e fare in modo che Form2 modifichi il testo (Text) proprio del Form che l'ha aperto.
    In questo caso mi basterà creare un opportuno campo pubblico in Form2 e assegnare a quel campo un riferimento al Form che sta per aprire (Show) la Form2, es:

    codice:
     
     
     
    Public Class Form1
     
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Form2.FormCheMiHaAperto = Me
    Form2.Show()
    End Sub
     
    EndClass
     
     
     
    Public Class Form2
     
    Public FormCheMiHaAperto As Form
     
    Private Sub Form2_Load(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Me.Load
    FormCheMiHaAperto.Text = "Io ti ho aperto!"
    End Sub
     
    End Class
    In questo esempio sono state usate le istanze di default (Form1 e Form2), ma funziona benissimo con qualunque altra istanza.

    Nel caso si debba accedere ad un metodo, o proprietà, o controllo (come ci si propone di fare nell'ambito di questa discussione) di un particolare tipo di Form (ad esempio Form1), allora sarà necessario dichiarare la variabile FormCheMiHaAperto di tipo opportuno. Nell'esempio di cui sopra, la dichiarazione diventa:

    Public FormCheMiHaAperto As Form1

    Dichiarando la variabile come Form generico, soltanto i membri della classe base (cioè Form) saranno accessibili in maniera diretta.


    Conclusione:

    Quello che potrebbe sembrare un argomento banale, in realtà per essere ben compreso richiede un minimo di approfondimento sulle basi del linguaggio. Infatti, l'introduzione delle istanze di default è andata incontro a chi vuole scrivere subito qualcosa, senza preoccuparsi di aprire un buon manuale.
    Personalmente, continuo a non usarle e ritengo che comunque si debba essere in grado di sapere come si gestisce la visibilità degli oggetti in una applicazione.
    Questa 'pillola' sull'accesso ai Form (ma come dicevo il concetto di base non si limita ai Form) vuole essere un aiuto a chi si trova di fronte al problema specifico, ma anche uno stimolo a cercare di capire la logica con cui gira il meccanismo della rilocazione degli oggetti e dei riferimenti che ad essi vengono assegnati.
    Ultima modifica di alextyx; 10-04-2007 14:13 

  2. #2
    L'avatar di alextyx
    alextyx non è in linea Moderatore Globale
    Luogo
    Prato
    Post
    2,585
    Data la diffusione di questo metodo, mi sono reso conto che sarebbe stata una grave mancanza non introdurlo in questo contesto.


    Passaggio di riferimento mediante la proprietà OWNER:


    Riportiamoci nell'evento click del pulsante che sta sul Form1.
    Come si può vedere, in quel codice istanziamo la Form2, e gli assegnamo la Form1 come 'Owner'

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim F2 As New Form2
    F2.Owner = Me
    F2.Show()
    EndSub

    A questo punto, sulla Form2, potremo scrivere, ad esempio:


    CType(Me.Owner, Form1).TextBox1.Text = "Pippo"

    Si noti che ancora una volta è necessaria una conversione esplicita al tipo Form1 per accedere a proprietà, metodi, eventi, campi e controlli che sono di quella particolare classe.
    La proprietà Owner, infatti, restituisce una classe Form generica e quindi in assenza di una specifica indicazione del tipo da essa derivato (Form1 nel nostro caso), sarebbero accessibili soltanto i membri pubblici della classe Form.

    Sarebbe, ad esempio possibile scrivere questo codice, che non necessita di una conversione di tipo (casting):

    Me.Owner.BackColor = Color.Red

    Ciò è possibile in quanto la proprietà BackColor è uno dei membri della classe Form.



  3. #3
    LAMORGY98 non è in linea Novello
    Post
    8

    Exclamation Non funziona

    Non ci riesco mi dà il seguente errore
    " non è accessibile in questo contesto perché è 'Private'. "- C:\Users\2A\Documents\SharpDevelop Projects\mw\mw\MainForm.vb:36

  4. #4
    L'avatar di AntonioG
    AntonioG non è in linea Moderatore Globale Ultimo blog: Commodore 64 e Codemotion
    Luogo
    Roma
    Post
    16,177
    Blogs
    5
    No LAMORGY98. Questo thread è del 2007 ! Non rispondere ad un thread così vecchio.

    Apri un nuovo thread e spiega quello che ti serve, mostrando il tuo codice che non funziona.
    Avvisi generali e importanti, a pena CHIUSURA thread e/o BAN
    Il crossposting è vietato.
    Le richieste di "pappa pronta" sono vietate.
    Utilizzate i tag CODE per il codice.
    Leggere il Regolamento per chiarimenti PRIMA di creare nuovi thread.
    Utilizzare sempre i PM per comunicare con i moderatori.
    Non mi contattate in PM per problemi di software, usate il forum

Discussione chiusa

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi