[VB.Net] Dynamisch erstellte Controls und der Zugriff darauf

Xervek

Mitglied
Hallo zusammen,

nachdem ich mich nun dusselig gesucht habe und irgendwie keine der Lösungen funktionieren wollte die ich im Internet gefunden habe wollt ich mal hier nachfragen.

Zu allererst einmal, es handelt sich um Visual Basic.Net 2005

Folgender Sachverhalt, ich bin grade am Testen mit dynamischen Controls, was soweit auch einigermaßen Funktioniert. Ich möchte mir in einer For-Schleife beliebig viele Textboxen dynamisch erstellen. Der Code dazu sieht folgendermaßen aus:

Code:
For i = 1 To 2
If i = 1 Then
            myTextBox.Name = (("Test" & i))
            Me.Controls("Test" & i).Top = 10
            Me.Controls.Add(myTextBox)
Else
            myTextBox.Name = (("Test" & i))
            Me.Controls("Test" & i).Top = 30
            Me.Controls.Add(myTextBox)
End If
Next

Wundert euch bitte nicht über die If-Abfrage, das ist einfach nur damit ich verstehe wie es läuft. Dieser Teil wird im Form-Load ausgeführt damit die Textboxen gleich zu beginn erstellt werden. Lustig zu beobachten ist nun allerdings, dass nur eine Textbox tatsächlich vorhanden ist, nämlich die 2. der Beiden. Textbox 1 ist komplett verschwunden, auch ist kein Zugriff darauf mehr möglich.

Der Zugriff erfolgt in einem Button folgendermaßen:

Code:
MsgBox(Me.Controls("Test2").Text)

Dieser Fall funktioniert noch problemlos, gleicher Code allerdings mit "Test1" funktioniert nicht mehr, es gibt folgenden Fehler: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."
In diesem Fall ist die Textbox einfach wieder verschwunden, ich weiß nicht wirklich warum und vorallem wohin. Die 1. Textbox wird erstellt, verschwindet aber sobald Textbox2 erstellt wird.

Das soll jetzt auch kein Ellenlanger Code werden den ich brauche, mich würde nur interessieren was mit der 1. Textbox passiert ist und wie ich per Button auf beide Textboxen zugreifen kann, beispielweise so:

Code:
MsgBox(Me.Controls("Test1").Text)
MsgBox(Me.Controls("Test2").Text)

nur kommt es wie gesagt zum bereits genannten Fehler da die 1. Textbox beim Erstellen der zweiten einfach verschwindet.

Auch möchte ich hinzufügen, dass diese Aufgabe keinen wirklichen Nutzen bietet außer dem, dass ich verstehen möchte wie es funktioniert, da ich dynamische Controls für ein anderes Programm brauche.

Liebe Grüße und vielen Dank im Voraus
 
Hi

Du musst auch jeweils eine neue Instanz der Klasse TextBox erzeugen! Derzeit überschreibst du beim zweiten Durchlauf deiner Schleife die erste Instanz.
 
Hallo,
dieses Problem habe ich auch gerade. Klar muss ich erst eine neue Instanz des dynamisch erzeugten Controls erzeugen. Doch wenn ich das tue ist das Problem immer noch: wie schaffe ich, dass das erzeugte Control dann zu benutzen, da ja kein statischer Code dafür vorhanden ist.
In Java kann ich einem auf diese Art erzeugten Control gleich den EventHandler mit geben und damit ist es in das normale EventHandling integriert und ich kann es dann z.B. verschieben, aktivieren usw.
Hierzu wurde einfach beim New die entsprechende Methode z.B. "MouseClick" implementiert EventHandler initialisiert. Fertig...
Wie geht das in VB.net?

Gruß
udk
 
Hi

Du musst auch jeweils eine neue Instanz der Klasse TextBox erzeugen! Derzeit überschreibst du beim zweiten Durchlauf deiner Schleife die erste Instanz.

Hallo,

vielen Dank für deine Antwort!

Entschuldige, wie mache ich das denn? Ich dachte ich erstelle eine neues Control mit "Me.Controls.Add("MeinName" & i)"? Wieso überschreibe ich da etwas?

Liebe Grüße
 
Hallo Xervec,
du änderst nur jeweils den Namen des Controls. Und erzeugst kein neues.
Wenn Du ein neues erzeugen willst, dann geht das mit New:
myTextBox = New TextBox
die anderen Eigenschaften der Textbox müssen dann von "Hand" gesetzt werden (Position, Größe, usw.)

Gruß
udk
 
Hallo udk,

vielen Dank für deine Antwort. Ich muss zu meiner Schande gestehen, dass ich es nun geschafft habe. Ich habe nur einen Fehler gemacht. Ich habe "myTextBox = New TextBox" am Anfang des Programms deklariert und nicht in der Sub selbst. Wenn ich dies in die For-Schleife einbaue funktioniert es.

Ich habe das nun so angewendet, habe aber trotz allem ein Problem das ich versuche kurz zu erklären (ich dachte ich könnte das mit dem jetztigen Wissen lösen).

Ich habe ein TabControl (ohne Tabs da diese dynamisch erstellt werden sollen). Nun möchte ich durch eine Schleife beliebig viele Tabs anlegen lassen und in jedem neu erstellten Tab auch ein ListView Control automatisch generieren. Hierbei heißt jede neuerstellte TabPage
"TabPage & i" (also je nach dem wie viele angelegt werden TabPage1, TabPage2, TabPage3, ...

Sowie das in dem jeweiligen Tab erstellte ListView mit den jeweiligen Namen "ListView & i" wordurch jedes Listview zu jedem Tab passt. Also
Listview1 befindet sich in TabPage1
Listview2 befindet sich in TabPage2
usw.

Wie kann ich nun auf das jeweilige Listview im Tabfeld per Doppelklick zugreifen? Ich habe mir hier einen Wolf gesucht.

Wenn ein Listview direkt auf dem Form liegt und nicht dynamisch erstellt wurde ist der Zugriff daurauf extrem einfach möglich, folgendermaßen:
ListView1.SelectedItems(0).SubItems(1).Text
(oder welches Element man auch immer aus der Listview braucht).

Allerdings schaffe ich es nicht, den Inhalt des jeweiligen im jeweiligen TabPage enthaltenen Listviews zu bekommen. Versuche wie:
Me.Controls("Listview1").SelectedItems(0).SubItems(1).Text
Schlagen fehl da:
Fehler 1 "SelectedItems" ist kein Member von "System.Windows.Forms.Control".

Wäre nett wenn mir das auch jemand erklären könnte.

P.S. ich hoffe ich habe es einigermaßen verständlich erklären können. Jeweils ein neues Tab und ein neues Listview das durchnummeriert wird. Darauf würd ich gern den Zugriff wissen (vorallem welches Event ich nehmen muss damit der Doppelklick auch funktioniert...).

Liebe Grüße und vielen Dank nochmals
 
Hallo,
versuch mal:
CType(Me.Controls("Listview1"), ListView).SelectedItems(0).SubItems(1).Text

Gruß
udk
 
Hallo,

leider funktioniert es nicht, daher gebe ich jetzt mal den Code fürs Erstellen der Tabs sowie der ListViews, stammen aus der MSDN, habe ein bisschen daran rumgebastelt damit es meinen Wünschen entspricht.

Code:
For Each existing_tab As String In My.Computer.FileSystem.GetFiles((My.Application.Info.DirectoryPath & "\locations\"), FileIO.SearchOption.SearchTopLevelOnly, "*.tab")
            tab_index = tab_index + 1

            FileOpen(1, (existing_tab), OpenMode.Input)
            Input(1, temp)
            Input(1, tabname)
            Input(1, temp)
            Input(1, filepath)
            FileClose(1)


            Me.tc_movies.TabPages.Add(tabname)
            Me.tc_movies.TabPages(tab_index).Name = "TabPage" & tab_index

            Call CreateMyListView()

        Next

Es wird also für jedes existierende .tab File ein eigenes Tab angelegt. Der Name nennt sich tc_movies (TabControl_Movies). Hier füge ich also bei jedem gefundenen einen Reiter hinzu und führe einen weiteren Codeabschnitt aus, welcher das jeweilige ListView hinzufügt. Folgendermaßen:

Code:
    Public Sub CreateMyListView()
        Dim listView1 As New ListView()


        ' Set the view to show details.
        listView1.View = View.Details
        ' Allow the user to edit item text.
        listView1.LabelEdit = True
        ' Give Size
        listView1.Height = 451
        listView1.Width = 754
        ' Allow the user to rearrange columns.
        listView1.AllowColumnReorder = True
        ' Display check boxes.
        'listView1.CheckBoxes = True
        ' Select the item and subitems when selection is made.
        listView1.FullRowSelect = True
        ' Display grid lines.
        listView1.GridLines = True
        ' Sort the items in the list in ascending order.
        listView1.Sorting = SortOrder.None

        listView1.Clear()

        Dim i As Integer
        ' Create three items and three sets of subitems for each item.
        For Each foundFile As String In My.Computer.FileSystem.GetFiles(filepath, FileIO.SearchOption.SearchTopLevelOnly, "*.ts", "*.pva", "*.mpg") 'FileIO.SearchOption.SearchAllSubDirectories, "*.ts")
            
            If foundFile.Contains("_") = True Then

                complete_filename = foundFile.Split("_")

                complete_filename(0) = Strings.Right(complete_filename(0), 5)
                complete_filename(0) = Strings.Replace(complete_filename(0), "-", ".")
                complete_filename(1) = Strings.Replace(complete_filename(1), "-", ":")
                complete_filename(3) = Strings.Left(complete_filename(3), complete_filename(3).Length - 3)


                Dim item1 As New ListViewItem(i) '"TV-Sendung") ', 0)
                ' Place a check mark next to the item.
                item1.SubItems.Add(complete_filename(0) & ". / " & complete_filename(1))
                item1.SubItems.Add(complete_filename(2))
                item1.SubItems.Add(complete_filename(3))
                item1.SubItems.Add(foundFile)
                listView1.Items.AddRange(New ListViewItem() {item1}) ', item2, item3})

i = i + 1

            Else
                MsgBox("Die folgende Datei ist nicht DVBViewer konform und wird daher nicht in die Liste aufgenommen:" & Chr(10) & foundFile & Chr(10) & Chr(10) & "Die Datei wurde in eine Liste unzulässiger Namen aufgenommen um die Meldung beim nächsten Programmstart zu unterbinden. Diese Liste kann mit einem Klick auf den entsprechenden Button gelöscht werden. Hierbei werden wieder alle im Verzeichnis befindelichen Dateien auf ihre Kompatibilität geprüft.", MsgBoxStyle.Information, "Unzulässige Dateien")
            End If
        Next

        ' Create columns for the items and subitems.
        listView1.Columns.Add("ID", 30, HorizontalAlignment.Left)
        listView1.Columns.Add("Datum/Uhrzeit", 100, HorizontalAlignment.Left)
        listView1.Columns.Add("TV Sender", 100, HorizontalAlignment.Left)
        listView1.Columns.Add("Aufnahme-Name", 550, HorizontalAlignment.Left)
        listView1.Columns.Add("Pfad-Name", 800, HorizontalAlignment.Left)

        tc_movies.TabPages(tab_index).Controls.Add(listView1)
        listView1.Name = "listView" & tab_index
    End Sub

Es funktioniert soweit absolut bestens, nur der Zugriff will nicht wirklich klappen. Ich bekomme mit deinem Vorschlag einen "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

Auch ist es nicht möglich mit einem Testbutton den Namen des jeweiligen Listviews herauszubekommen.
MsgBox(Me.Controls("ListView0").Name) oder
MsgBox(Me.Controls("ListView1").Name) , usw. enden alle in einem "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

Bin ein bisschen ratlos.

Vielen Dank im Voraus
 
Hallo Xervec,
in deinem Code sehe ich, dass du die ListViews in den Container
tc_movies.TabPages(tab_index).Controls.Add(listView1)
hinzufügst. Lesen möchtest Du sie allerdings aus dem Controls Container deiner Hauptform.
Das geht latünich nich.
Sprich: wenn Du später auf die ListViews zugreifen möchtest, dann musst Du sie aus dem Container holen, in den Du sie hereingetan hast. Also:
MsgBox(Me.tc_movies.TabPages(tab_index).Controls("ListView0").Name)

Ich hoffe, dass t

Gruß
udk
 
Heyho,

wunderbar, vielen, vielen Dank, es funktioniert nun bestens und ausgezeichnet. Eine letzte Frage stellt sich aber doch noch...

Wie komme ich nun an das Event DoubleClick im Bezug auf die ListViews? Ich möchte bei einem Doppelklick in das jeweilige Listview die Ausgabe des ersten SubItems haben.

Dashier funktioniert soweit (sofern es über einen Button läuft) allerdings weiß ich nicht, wie ich an das Doubleklick Event kommen kann...

Code:
tab_index = Me.tc_movies.SelectedIndex
MsgBox(CType(Me.tc_movies.TabPages(tab_index).Controls("Listview" & tab_index), ListView).SelectedItems(0).SubItems(1).Text)

Danke schonmal :)
 

Neue Beiträge

Zurück