none
Ein Array von Steuerelementen erzeugen RRS feed

  • Frage

  • Hallo zusammen,
    mit Dim a as ...  kann man jedes beliebige Objekt deklarieren.
    Das müsste doch auch mit Arrays gehen. Dim a() as ....
    Ich möchte ein Array von Steuerelementen gleicher Klasse erzeugen, damit ich später
    indiziert darauf zugreifen kann.
    Folgendes Beispiel:
    public class form1 
    
       ' ein array field der Klasse Label deklarieren:
       Dim fields() As System.Windows.Forms.Label
       ' geht
    
    
       Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load
    
    
            ' die erste Instanz von fields erzeugen
            Dim fields = New System.Windows.Forms.Label()
            ' geht
    
            ' Eigenschaften von fields setzen von default_Label der gleichen Klasse
            '
            fields = default_Label
            ' geht
    
    
            'jetzt fields mit Eigenschaften versehen und zwar X und Y Position
            'dazu einen Typ xyloc erzeugen:
            Dim xyloc As System.Drawing.Point = New System.Drawing.Point()
    
            ' und mit Werten versehen:
            xyloc.X = 30
            xyloc.Y = 100
    
            Jetzt Steuerelement fields mit Koordinaten versehen
            Dim i As Integer = 0
          
            fields(i).Location = xyloc
    
           ' Ende der Vorstellung 
    
    
    
    'Fehler	1 Die Klasse "System.Windows.Forms.Label" kann nicht indiziert werden, da sie keine 'Standardeigenschaft hat.
    
    end sub
    
    
    
    
    end class
    
    Frage: Wie bekomme ich das hin?
    Gruß
    Ellen
    Freitag, 6. November 2009 13:05

Antworten

  • Hallo Ellen,

    statt einem Array, empfiehlt sich eine List(Of T). Das ist aber nicht der Grund, dass Dein Vorhaben scheitert. Der liegt darin, dass Du innerhalb von Form_Load eine lokale Variable "fields" deklariert, die Vorrang vor der Klassenvariable fields() hat, solange Du nicht das Schlüsselwort "Me" voranstellst. Also "Me.fields(x) = ...".

    Scope in Visual Basic
    http://msdn.microsoft.com/en-us/library/1t0wsc67.aspx

    Anbei ein Beispiel mit List(Of T):


    Public Class Form1 
    
       ' ein array field der Klasse Label deklarieren:
       Dim fields As List(Of System.Windows.Forms.Label)
    
       Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load
    
            ' Liste initialisieren:
            fields = New List(Of System.Windows.Forms.Label)
    
            ' Eigenschaften von fields setzen von default_Label der gleichen Klasse
            '
            fields.Add(default_Label)
    
            'jetzt fields mit Eigenschaften versehen und zwar X und Y Position
            'dazu einen Typ xyloc erzeugen:
            Dim xyloc As System.Drawing.Point = New System.Drawing.Point(30, 100)
    
            ' Jetzt Steuerelement fields mit Koordinaten versehen
            Dim i As Integer = 0
          
            fields(i).Location = xyloc
    
       End Sub
    End Class

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Freitag, 6. November 2009 13:27
    Moderator
  • Hallo Ellen,

    Du erzeugst ja keine zweite Instanz, sondern arbeitest generell mit der vom Designer erzeugten Instanz Deines Labels. Eine neue Instanz erzeugst Du über das Schlüsselwort "New":

      Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load  
     
            ' Berechnung der Koordinaten
            Dim xyloc As System.Drawing.Point = New System.Drawing.Point()
            xyloc.X = RichTextBox_RX.Left
            xyloc.Y = RichTextBox_RX.Top + RichTextBox_RX.Height + Ydiff
    
            fields = New List(Of System.Windows.Forms.Label)
    
    	For i As Integer = 0 To 5
                xyloc.Y += 50 * i
                Dim lbl = New System.Windows.Forms.Label()
    
                lbl.Location = xyloc
                lbl.Text = String.Format("Label {0}", i)
    
                Me.Controls.Add(lbl)
                fields.Add(lbl)
            Next
        End Sub

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    • Als Antwort markiert Ellen Ramcke Mittwoch, 19. Mai 2010 14:43
    Freitag, 6. November 2009 16:47
    Moderator

Alle Antworten

  • Hallo Ellen,

    statt einem Array, empfiehlt sich eine List(Of T). Das ist aber nicht der Grund, dass Dein Vorhaben scheitert. Der liegt darin, dass Du innerhalb von Form_Load eine lokale Variable "fields" deklariert, die Vorrang vor der Klassenvariable fields() hat, solange Du nicht das Schlüsselwort "Me" voranstellst. Also "Me.fields(x) = ...".

    Scope in Visual Basic
    http://msdn.microsoft.com/en-us/library/1t0wsc67.aspx

    Anbei ein Beispiel mit List(Of T):


    Public Class Form1 
    
       ' ein array field der Klasse Label deklarieren:
       Dim fields As List(Of System.Windows.Forms.Label)
    
       Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load
    
            ' Liste initialisieren:
            fields = New List(Of System.Windows.Forms.Label)
    
            ' Eigenschaften von fields setzen von default_Label der gleichen Klasse
            '
            fields.Add(default_Label)
    
            'jetzt fields mit Eigenschaften versehen und zwar X und Y Position
            'dazu einen Typ xyloc erzeugen:
            Dim xyloc As System.Drawing.Point = New System.Drawing.Point(30, 100)
    
            ' Jetzt Steuerelement fields mit Koordinaten versehen
            Dim i As Integer = 0
          
            fields(i).Location = xyloc
    
       End Sub
    End Class

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Freitag, 6. November 2009 13:27
    Moderator
  • Hallo Thorsten,
    so funktioniert es jetzt.

    Ein Fehler ist noch da. Wenn ich die 2te Instanz zur Liste hinzufüge, wird nur noch das 2te Steuerelement in der Form angezeigt.
    Das erste ist unsichtbar. Entferne ich die Anweisungen zur zweiten Instanz, wird wieder das erste Element angezeigt.
    Es sollen 2 Label in der Form zur Anzeige kommen im Abstand Y von 50 Pixel und X = 30 vom linken Rand der Form.
    Label_Time ist mit dem Formdesigner erzeugt. Alle Label sollen diese Eigenschaften haben. (gleich aussehen)
    Hier der Code.
    (Der Aufbau der Elemente wird später in einer Loop erfolgen. Das hier ist nur zum Test.)

    Gruß
    Ellen
    Public Class Form1__CC
    
        Const Ydiff As Integer = 30
        Dim fields As List(Of System.Windows.Forms.Label)
    
        Dim xstart As Integer
        Dim ystart As Integer
    
     
        ' ---------------------------------------------------------------
        '                      Windows form aufbauen
        '---------------------------------------------------------------
        Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load
    
      
     
            ' Berechnung der Koordinaten
            Dim xyloc As System.Drawing.Point = New System.Drawing.Point()
            xyloc.X = RichTextBox_RX.Left
            xyloc.Y = RichTextBox_RX.Top + RichTextBox_RX.Height + Ydiff
    
            fields = New List(Of System.Windows.Forms.Label)
            Dim i As Integer = 0
    
            'erste Instanz erzeugen
            fields.Add(Label_Time)
            fields(i).Location = xyloc
            fields(i).Text = "1111"
            Me.Controls.Add(fields(i))
    
            'zweite Instanz erzeugen
            i = 1
            fields.Add(Label_Time)
            xyloc.Y += 50
            fields(i).Location = xyloc
            fields(i).Text = "2222"
            Me.Controls.Add(fields(i))
    
        End Sub
    end class
    
    Freitag, 6. November 2009 16:20
  • Hallo Ellen,

    Du erzeugst ja keine zweite Instanz, sondern arbeitest generell mit der vom Designer erzeugten Instanz Deines Labels. Eine neue Instanz erzeugst Du über das Schlüsselwort "New":

      Private Sub Form1_Load(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles MyBase.Load  
     
            ' Berechnung der Koordinaten
            Dim xyloc As System.Drawing.Point = New System.Drawing.Point()
            xyloc.X = RichTextBox_RX.Left
            xyloc.Y = RichTextBox_RX.Top + RichTextBox_RX.Height + Ydiff
    
            fields = New List(Of System.Windows.Forms.Label)
    
    	For i As Integer = 0 To 5
                xyloc.Y += 50 * i
                Dim lbl = New System.Windows.Forms.Label()
    
                lbl.Location = xyloc
                lbl.Text = String.Format("Label {0}", i)
    
                Me.Controls.Add(lbl)
                fields.Add(lbl)
            Next
        End Sub

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    • Als Antwort markiert Ellen Ramcke Mittwoch, 19. Mai 2010 14:43
    Freitag, 6. November 2009 16:47
    Moderator
  • Hallo Thorsten,
    ich möchte mein Feedback geben.
    Es läuft jetzt, wie ich es mir vorgestellt habe.

    Ich habe das aufgearbeitet und fasse zusammen:

    1.) Class List(Of T)
    Da wäre ich allein nicht drauf gekommen. Wie schön, dass es Foren gibt.
    Ich lese täglich in der Msdn Library und finde Sachen, welche man irgendwann
    gebrauchen kann. Die Library ist mächtig. Für einen Anfänger ist es sehr schwer
    da zurecht zufinden. Den anderen geht es wohl genauso.

    2.) fields() und fields
    Ich habe das tatsächlich 2mal deklariert. In der Methode und in der Klasse.
    Deswegen hat der Compiler zunächst auch nicht gemeckert.
    Mein Fehler. Jetzt habe ich es verstanden.

    3.) fields = default_Label
    Auf beiden Seiten steht der gleiche Typ. Deswegen funktioniert diese Anweisung auch.
    Nur damit erzeuge ich keine neue Instanz. Die Instanz wird nach fields kopiert und nur
    diese ausgeführt. Das Element default_Label verschwindet zur Laufzeit von der Form.

    4.) Me.fields und fields
    Me referenziert auf die aktuelle Klasse und fields lokal auf die Methode.
    Aber nur dann, wenn auch lokal definiert. Sonst geht der Verweis zurück auf die
    Klasse. Den Fehler machen wohl viele. Habe ich hier schon einmal gesehen.

    5.) fields.Add(Label_Time)
    Siehe meinen Code (black & white). Mit dem Debugger kann man nachvollziehen, dass
    tatsächlich 2 Listeneinträge entstehen. Wenn Du die genau betrachtest, sind sie absolut
    identisch, nämlich Label_Time. Auch die Handles sind identisch. Was heist das? Es ist keine
    neue Instanz enstanden, sondern eine Kopie. Und nur diese( die letzte)  wird auch ausgeführt.
    Wenn ich die Zeile

    fields.Add(Label_Time) ersetze mit dieser:

    fields.Add(New System.Windows.Forms.Label) geht es.
    Die Eigenschaften von Label_Time müssen in einzelnen Anweisungen
    nach fields kopiert werden. Dann haben die neuen erzeugten Label auch das gleiche Aussehen.

    Das ist im Prinzip auch das, was Du vorgeschlagen hast.

    6.) Objektorientierung
    Dieses ist ein schönes Beispiel wie man aus seinem "Lieblings" Steuerelement auch eine
    Klasse erzeugen könnte von der die anderen(children) dessen Eigenschaften erben.
    Das kommt später dran. Soweit bin ich noch nicht.


    Vielen Dank und schöne Grüße
    Ellen


    • Als Antwort markiert Ellen Ramcke Samstag, 7. November 2009 20:06
    • Tag als Antwort aufgehoben Ellen Ramcke Donnerstag, 20. Mai 2010 19:29
    Samstag, 7. November 2009 11:26