Wie auf Steuerelementeigenschaft über Variable zugreifen?

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Blackm1nd.

    Wie auf Steuerelementeigenschaft über Variable zugreifen?

    Es sollen mehrere Textboxen (>10 Stück) mit Strings aus einem Array befüllt werden. Dazu habe ich die Textboxen nummeriert (txtb1, txtb2, ..., txtb20) und bräuchte nun variablenhaften Zugriff auf die Name-Eigenschaft.
    Ich kann leider nicht vorhersehen, wieviele Textboxen genau generiert werden sollen (ergibt sich aus dem Datenmaterial), sonst würde ich es "fest verdrahten" :)

    Aus den Ansätzen, die sich aus der Googlesuche ergaben, erschien mir folgender am vielversprechendsten:

    VB.NET-Quellcode

    1. Dim strTxtName As String
    2. strTxtName = "txtb" + zaehler.ToString
    3. Me.Controls(strTxtName).Text = Item

    "Item" ist ein String, der aus einem Textfieldparser stammt und enthält auch einen Wert.

    Nun bekomme ich jedoch zur Laufzeit eine NullReferenceException in der letzten Zeile.
    Aus diesem Thread: http://www.vb-paradise.de/programmieren/grundlagen/65146-der-objektverweis-wurde-nicht-auf-eine-objektinstanz-festgelegt/ weiß ich, dass man eine neue Instanz einer Klasse mit "New" anlegen muss. Meine diesbezüglichen Versuche scheiterten jedoch, was mich nicht wundert, da ich nicht genau verstanden habe um was es in diesem Fall geht.

    Für mich ist der Bezeichner "Me.Controls": Steuerelemente der Form, "(Steuerlementname)" und ".Text": Eigenschaft, der ich einen Wert im gleichen Datentyp zuweisen kann, recht eindeutig. Aber ich bin ja auch Anfänger.

    Kann mir da jemand helfen?
    for each tb as textbox in me.controls.oftype(of textbox)
    debug.print(tb.name)
    next

    Was zeigt er dann an?

    Denn in "Me".controls ist natürlich nur das drin, was DIREKT in der Form (bzw "Me", das kann ja jedes Control sein) ist. Wenn deine Textboxen in nem Panel wären, wäre die Syntax
    me.panel1.controls...
    oder wenn ein einer Groupbox in nem Panel
    me.panel1.groupbox4.controls ...
    Im Direktfenster wird nichts ausgegeben.

    Die Textboxen habe ich zum Testen erstmal "einfach so" auf das Formular gezogen, da das endgültige Layout noch längst nicht festgelegt werden kann.

    Hier aus Form1.Designer:

    VB.NET-Quellcode

    1. ...
    2. Private Sub InitializeComponent()
    3. Me.txtb1 = New System.Windows.Forms.TextBox()
    4. Me.txtb5 = New System.Windows.Forms.TextBox()
    5. Me.txtb4 = New System.Windows.Forms.TextBox()
    6. Me.txbt3 = New System.Windows.Forms.TextBox()
    7. Me.txtb2 = New System.Windows.Forms.TextBox()
    8. ...
    9. 'txt1
    10. '
    11. Me.txtb1.Location = New System.Drawing.Point(15, 72)
    12. Me.txtb1.Name = "txtb1"
    13. Me.txtb1.Size = New System.Drawing.Size(146, 20)
    14. Me.txtb1.TabIndex = 16
    15. ...
    16. Friend WithEvents txtb2 As System.Windows.Forms.TextBox
    17. Friend WithEvents txtb3 As System.Windows.Forms.TextBox
    18. Friend WithEvents txtb4 As System.Windows.Forms.TextBox
    19. Friend WithEvents txtb5 As System.Windows.Forms.TextBox
    20. Friend WithEvents txtb1 As System.Windows.Forms.TextBox
    21. ...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Blackm1nd“ ()

    Blackm1nd schrieb:

    Im Direktfenster wird nichts ausgegeben.

    Sollte man vlt im AUSGABEfenster mal schauen ;)

    EDIT BTW:
    Me.txtb1.Name = "txt1"

    Du nennst deine Textboxen txtNUMMER und nicht txtbNUMMER ;) Sollte man schon drauf achten, dass man das was man sich gedacht hat, dann auch so macht ...

    EDIT2:
    Ach so .... Du bist einem Denkfehler aufgesessen! Controls(String) sucht das Control nicht anhand des Namens der Control-Variable sondern anhand der .Name Eigenschaft! Die sind zwar "normalerweise" erstmal gleich, aber das muss nicht sein - wie du siehst ;)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „picoflop“ ()

    Hab ich mich erschrocken :)

    Nein, ich denke mal, das ist das gleiche, weil ich noch andere Ausgaben zum Testen mit Debug.Print erstellen lasse, und die werden im Direkt-/Ausgabefenster ganz normal angezeigt.

    Edit: (Leider) hat das alles seine Richtigkeit; dass da oben "txt1" anstelle von "txtb1" stand, war ein Fehler meinerseits im Einfügen des Codes hier in das Forum. Die Textboxen heißen in Wirklichkeit noch ganz anders, aber für das Forum habe ich einfachere Namen gewählt wegen der Übersichtlichkeit/Tipparbeit.
    Die Werte der Eigenschaften und die Bezeichnungen im Code sind konsistent, das habe ich soeben noch einmal überprüft.

    Edit2: Ist der Unterschied zwischen dem Namen des Controls und dem Namen der Eigenschaft folgender:
    Name des Controls="txtb1 System.Windows.Forms.TextBox" und
    Name der Eigenschaft=das, was als Wert in (Name) in den Eigenschaften ausgewiesen wird?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Blackm1nd“ ()

    wie picoflop andeutet, werden hier leicht 2 unvereinbare Ebenen durcheinander gebracht: Der CodeName eines Controls und seine .Name-Property.

    der CodeName - etwa Textbox1 ist etwas, was nur im Editor des Programmierers existiert, im laufenden Programm ist die Textbox nur eine SpeicherAddresse.

    Die Name-Property hingegen ist halt eine Property dieser Textbox.

    Beides hat nichts miteinander zu tun, und wird leider nur leicht verwechselt.

    Tatsächlich ist die .Name-Property im Grunde zu nichts nütze - es gibt in jedem Fall bessere herangehensweisen, als über die Name-Property auf ein best. Control zuzugreifen.

    Aber auch das ist u.U. erstmal egal, denn anstatt viele Textboxen zu generieren, soll man lieber ein DataGridview nehmen. Das frisst weniger Resourcen, ist leichter zu handhaben, und passt auch einfach von der Logik her besser zur Anforderung, welche vermutlich ist, eine Liste von Daten editierbar zu präsentieren.
    So gerade nach Hause gekommen, frisch ans Projekt gesetzt und die Lösung dann schnell gefunden:

    Das Problem lag natürlich (wie so oft) zwischen Stuhl und Monitor. Ich habe im Form Designer herumgeblättert und mir ist dabei aufgefallen, dass die Textboxen doch in einem Container lagen (Me.ToolStripContainer1.ContentPanel). Dunkel erinnere ich mich, wie ich eine Statusleiste einfügen wollte, mit dem Toolsstrip herumgespielt hatte, es nicht funktionierte und ich den Container nicht mehr wegbekam :)
    Naja, die Form wird eh komplett neu gemacht wenn der Inhalt fertig ist.

    picoflops Diagnosecode:

    VB.NET-Quellcode

    1. For Each tb As TextBox In Me.ToolStripContainer1.ContentPanel.Controls.OfType(Of TextBox)()
    2. Debug.Print(tb.Name)
    3. Next
    hat nach der Anpassung sofort alle Textboxnamen ausgegeben.

    Der Rest war ein Kinderspiel:

    VB.NET-Quellcode

    1. Dim strTxtName As String
    2. strTxtName = "txtb" + count_items_per_row.ToString
    3. Me.ToolStripContainer1.ContentPanel.Controls(strTxtName).Text = Item
    funktioniert in meinem Kontext nun einwandfrei.

    Da ich nun schon im Flow war, habe ich gleich die Textboxen aus der Anzahl der Items dynamisch generieren und füllen lassen:

    VB.NET-Quellcode

    1. '"Index" (Integer) ist der Zähler für die Zeilen in einer Textdatei.
    2. 'In der ersten Zeile stehen die Überschriften. Für diese wird nun jeweils eine Textbox generiert.
    3. '"count_items_per_row" (Integer) ist der Zähler für die Anzahl der Items pro Zeile.
    4. '"Item" (String) beinhaltet den Zelleninhalt, in der ersten Zeile also eine einzelne Überschrift einer Spalte.
    5. If Index = 1 Then
    6. Dim tmp_tb As New TextBox
    7. tmp_tb.Name = "txtb" + count_items_per_row.ToString
    8. tmp_tb.Location = New Point(count_items_per_row * 50 - 40, 80)
    9. tmp_tb.Width = 50
    10. tmp_tb.Visible = True
    11. Me.ToolStripContainer1.ContentPanel.Controls.Add(tmp_tb)
    12. tmp_tb.Text = Item
    13. tmp_tb.Update()
    14. End If

    Das war jetzt nur zur Info falls es jemanden interessieren sollte.
    Kaum macht man es richtig, schon funktioniert's :)

    Die Anforderung ist übrigens Tabellen, bzw. CSV Dateien, die mehrere 10K Messdaten enthalten, nach Setzen von Grenzwerten zu kategorisieren, visualisieren, Unterschiedsprüfungen (Signifikanztests) zwischen den Kategorien vorzunehmen und die Daten dementsprechend zu filtern. Ich werde also vermutlich noch öfter zu irgendwelchen Details Fragen stellen.

    Vorerst bedanke ich mich bei allen Beteiligten für die Hilfe.

    Blackm1nd schrieb:

    Die Anforderung ist übrigens Tabellen, bzw. CSV Dateien, die mehrere 10K Messdaten enthalten, nach Setzen von Grenzwerten zu kategorisieren, visualisieren, Unterschiedsprüfungen (Signifikanztests) zwischen den Kategorien vorzunehmen und die Daten dementsprechend zu filtern.

    und das hast du vor, in Textboxen zu verwursten?

    gugge vlt. erst noch Most Primitive, EinzelblattView-Post, coloriertes DatagridView, und wg. Filtern: DataExpressions

    ErfinderDesRades schrieb:

    und das hast du vor, in Textboxen zu verwursten?

    Vermutlich nicht, da er ja nur die Spaltenüberschriften ausliest. Wir können wohl auch davon ausgehen, dass er x-tausend Messwerte nicht in Rohform und schriftlich darstellen will. Auch "visualisieren" spricht eher gegen eine Anzeige in lesbarer Schriftform sondern scheint vielmehr auf irgendetwas "graphisches" hinzudeuten.
    Ohne Details natürlich Rainer Speckulazion ;)
    @picoflop: l0l :)

    Richtig, denn die Rohdaten, die in mein Programm importiert werden, liegen beim Benutzer ja schon vor (meist als Excel oder Matlab Datei) und müssen deshalb nicht noch einmal angezeigt werden. Der Benutzer muss jedoch die Überschriften sehen, damit er weiß, mit welchen Daten er aktuell arbeitet. Die Daten selbst verbleiben im Array und dürfen auch nicht verändert werden (Messdaten!).

    Aber trotzdem danke für die Links, ErfinderDesRades, die Infos werde ich sicherlich noch einmal gebrauchen können.

    Wo wir grad schonmal Offtopic sind: Wenn ich einen Scatterplot machen möchte (einen zweidimensionalen Punkt setzen) bei, sagen wir 1000 zu zeichnenden Punkten, der bei Änderung der Filterkriterien (Punkte fallen weg oder kommen hinzu) wirklich schnell aktualisiert, wohin orientiere ich mich am besten? Gleich DirectX? Oder gibt es da überhaupt Erfahrungswerte? Hätte ich besser mit WPF anfangen sollen?
    Die Literatur bei Google ist bezüglich Scatterplots reichlich dünn gesät :-/