Newsgroup: it.comp.lang.visual-basic
Titolo: [NET] Problema con le matrici di controlli

Ciao a tutti, sto portando alcune form di un progetto in visual Basic
6.0 in Visual Basic .NET ma mi sono subito inbattuta in alcuni
problemi.
Devo popolare una serie di label (creati come una matrice da 0 a 17)
che prima venivano popolate tramite un recordset di ADO dichiarato
globale in un modulo.
Per ovviare a tutto ciò o dichiarato un Dataset di ADO NET in un
modulo e accedo agli elementi con la seguente istruzione:
DataSTransito.Tables(0).Rows(IndiceRigaDataSet).Item("c/o")
Questo sembra funzionare ma poi quanto mi trovo nella necessità di
scorrere le mie label non so + come fare... Il vecchio codice è il
seguente:
For i = 0 To 17
   If Trim(label(i).Text) <> "" Then
      .........
   Else 
      .........
   end if
next i
Ho provato a dichiarare una variabile 
Dim x as label
e poi all'interno del ciclo:
x.name
="label_" & i --> gli elementi della matrice mi sono stati
convertiti in nome_ indice...
ma non funziona...
qualcuno è in grado di darmi un consiglio o magari fornirmi un
esempio?
Grazie in anticipo
Giulia

 ma non funziona...
Come detto, non e' piu' possibile utilitare gli array di controlli alla
vecchia maniera, quello che vedi qui e' il tentativo del wizard di
conversione di restituire qualcosa che possa piu' o meno essere simile... a
questo proposito, i controlli "reali" della matrice vengono convertiti con
la nomenclatura che hai visto, ma in piu' viene creato un ulteriore oggetto
di tipo Microsoft.VisualBasic.Compatibility.VB6.LabelArray con il nome *e le
proprieta'* dell'array originario.
Il vecchio ciclo quindi deve continuare a funzionare come prima, senza
modifiche di sintassi; come riferimento ecco un codice di esempio in VB6,
che e' stato convertito  dal wizard senza problemi:
Private Sub Command1_Click()
Dim i As Integer
For i = 0 To Label1.UBound
    Label1(i) = "Label " & i
Next
End Sub
questo il codice creato in fase di definizione della form (array di 5
elementi)
#Region "Windows Form Designer generated code "
...
Public WithEvents _Label1_4 As System.Windows.Forms.Label
Public WithEvents _Label1_3 As System.Windows.Forms.Label
Public WithEvents _Label1_2 As System.Windows.Forms.Label
Public WithEvents _Label1_1 As System.Windows.Forms.Label
Public WithEvents _Label1_0 As System.Windows.Forms.Label
Public WithEvents Label1 As
Microsoft.VisualBasic.Compatibility.VB6.LabelArray
...
e questo il codice corrispondente al pulsante
Private Sub Command1_Click(ByVal eventSender As System.Object, _
    ByVal eventArgs As System.EventArgs) Handles Command1.Click
Dim i As Short
For i = 0 To Label1.UBound
    Label1(i).Text = "Label " & i
Next
End Sub
che come vedi, tipi a parte, e' perfettamente identico.
Ora, anche se questa cosa funziona (ricontrolla il tuo progetto perche'
dovrebbe andare anche a te...) non e' particolarmente felice perche', come
avrai notato da te, genera parecchia "rumenta" per simulare i vecchi
meccanismi; tutto il codice generato automaticamente dal wizard andrebbe
considerato, per come la vedo io, solo come un espediente temporaneo e per
quanto mi riguarda dubito che lo usero' mai in alcun progetto serio... la
dura verita' e' che bisogna riscrivere il codice, perche' ormai il
linguaggio e' tutta un'altra cosa.
Per gli array di controlli ad esempio (detto brevemente in due parole) si
puo' tranquillamente utilizzare un sistema basato sulla definizione di
"veri" array (Es. Dim Label1() As System.Windows.Forms.Label) che verranno
popolati a runtime creando al volo i controlli richiesti o impostando un
riferimentro ad altri definiti in design, i cicli a questo punto vengono da
se, mentre con AddHandler puoi far collimare gli eventi dei singoli
controlli in un unico gestore, come avveniva in VB6, e tramite il parametro
sender puoi verificare di volta in volta quale e' stata l'origine
dell'evento, quello che prima veniva fatto dal parametro Index.
Ciao
-- 
Luca Dormio - 
luca....@tin.it
________________________________
"Marty, non stai ragionando in maniera quadridimensionale"
Dr. Emmett L. Brown

 Ciao
Ciao Luca, sei stato veramente gentile e chiaro nella tua risposta e
ti ringrazio veramente tanto. Ti disturbo ancora per chiederti una
cosa.
A proposito del tuo suggerimento io ho fatto nel seguente modo:
- ho creato una matrice che viene popolata da una routine a parte con
il valore delle singole text esempio:
matrice(0)=text_0.text
...
e poi nei miei vecchi cicli ciclo sulle matrici e non + sui controlli.
posso chiederti come si fa a "...impostando un riferimentro ad altri
definiti in design" come mi hai scritto?
grazie ancora
giulia

 definiti in design" come mi hai scritto?
Quello che intendevo e' di salvare nella matrice un riferimento all'intero
controllo, non soltanto ad una property come hai fatto piu' sopra... a
questo punto puoi trattare l'array in maniera del tutto simile a quanto
facevi con VB6.
La differenza tra definito in design o meno, dipende solo dalla scelta che
fai di raggruppare in un array un insieme di controlli disegnati in fase di
progettazione, piuttosto che creati al volo.
Giusto per farti un esempio, piazza una form vuota e incolla questo codice,
che genera una matrice di 5 label tutta a runtime
Public Class Form1
    Inherits System.Windows.Forms.Form
    Private arLabels(4) As Label
    Private Sub Form1_Load(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) Handles MyBase.Load
        Dim i As Short
        'generiamo 5 istanze di label, incolonnate verticalmente
        For i = 0 To 4
            arLabels(i) = New Label
            'assegnamo un nome di comodo, il formato non e' realmente
importante
            arLabels(i).Name = String.Format("Label_{0}", i)
            arLabels(i).Text = String.Format("Sono la label {0}", i)
            arLabels(i).SetBounds(20, 20 + (50 * i), 150, 50)
            'assegnamo a tutte un unico gestore di evento, come in un
"vecchio"
            'Array di controlli
            AddHandler arLabels(i).Click, AddressOf AllLabels_Click
        Next
        'aggiungiamo in blocco i nuovi controlli alla form
        Me.Controls.AddRange(arLabels)
    End Sub
    Private Sub AllLabels_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs)
        Dim lbl As Label
        'esempio di ciclo sull'array
        For Each lbl In arLabels
            lbl.BackColor = System.Drawing.Color.Yellow
        Next
        'Esempio di accesso alla sorgente dell'evento
        lbl = DirectCast(sender, Label)
        lbl.BackColor = System.Drawing.Color.Red
        Select Case lbl.Name
            Case "Label_0"
                Me.Text = "Sono la prima"
            Case "Label_1"
                Me.Text = "Sono la seconda"
            Case "Label_4"
                Me.Text = "Sono l'ultima"
            Case Else
                Me.Text = "Siamo in mezzo"
            End Select
        End Sub
End Class


 
Grazie... scusa un ultima domanda, se non volessi creare a run-time le
label perchè le ho già piazzate sul form (conta che ne ho circa
50...)come posso fare per scorrerle e cambiare il backcolor? Devo
creare una matrice di label o una collection. Scusa ho provato a
maneggiare un po' sul codice che mi hai inviato ma non sono riuscita a
concludere niente...
Grazie ancora

 creare una matrice di label o una collection.
La logica resta tutta uguale, soltanto in fase di generazione dell'array non
devi creare una nuova istanza di controllo ogni volta, ma impostare un
riferimento a quelle esistenti.
Quindi invece di
arLabels(i) = New Label
arLabels(i).Name = String.Format("Label_{0}", i)
usi semplicemente
arLabels(i) = <istanza di controllo gia' esistente, che ha anche gia' un
nome>
e puoi omettere del tutto
Me.Controls.AddRange(arLabels)
perche' i controlli definiti in design appartengono gia' alla collection dei
controls della form.
Naturalmente in questo caso, se non hai un qualche denominatore comune, non
puoi fare un ciclo, ma devi ripetere 50 volte arLabels(..) = ..
Altrimenti puoi provare qualcosa del genere
Dim Control As Control
Dim i As Integer
Dim arText() As TextBox
For Each Control In Me.Controls
    'per es. raggruppiamo in un array tutti i textbox esistenti sul form
    'ma solo se il nome comincia per 'txtArray'
    If TypeOf Control Is TextBox AndAlso Control.Name.StartsWith("txtArray")
Then
        ReDim Preserve arText(i)
        arText(i) = DirectCast(Control, TextBox)
        i += 1
    End If
Next


Grazie 1000 ho risolto!
Giulia