Form aus Array instanzieren

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Form aus Array instanzieren

    Hallo zusammen,

    ich habe vor ein paar Formen in einer Arraylist zu sammeln. Diese sollen dann je nach Bedarf geladen werden können. Das war mein erster Versucht,
    welcher aber ja nicht funktionieren kann, bzw. nur einmal funktioniert.

    VB.NET-Quellcode

    1. Dim f As New ArrayList
    2. Dim d As Form
    3. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    4. f.Add(New Form2)
    5. f.Add(New Form3)
    6. End Sub
    7. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    8. d = f.Item(1)
    9. d.Show()
    10. End Sub


    Was ja auch keine Wunder ist, da ich ja keine Instanz der Form habe.
    Jetzt habe ich es so versucht.

    VB.NET-Quellcode

    1. d = New f.Item(1)


    Das funktioniert aber nicht. Es kommt immer die Meldung "Der Typ f.Ite ist nicht definiert". Wie kann ich das Problem lösen?

    Ich hoffe ihr könnt mir helfen!
    Gruß
    ArrayList sollte man nicht verwenden. Gugge böse Funktionen

    vermutlich bei Galileo gelernt, oder? Also Proggen lernt man besser mit dieses Buch Lesen.

    Verwende List(Of Form)

    achso -
    Und das heißt für mich?

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. f(1).Show()
    3. End Sub
    Aber f muss halt eine List(Of Form) sein

    demmy schrieb:

    Was ja auch keine Wunder ist, da ich ja keine Instanz der Form habe.


    Das ist wohl nicht das Problem, mit "f.Add(New Form2)" wird eine neue Instanz von Form2 hinzugefügt. Wenn du es mit einer List(Of Form) anstatt mit einer ArrayList versuchst solltest du den Fehler: "Der Typ f.Ite ist nicht definiert" nicht mehr haben.
    Achso ok, ich glaube ich hab mich ein wenig unverständlich ausgedrückt, mein Fehler.
    Was ich eigentlich meinte ist, dass ich nach dem Auslesen aus dem Array eine Instanz der Form brauche. Die Form soll durch eine Variable in die Liste eingelesen werden.
    Diese Variable kann ich leider nicht mit "new" einlesen. Das heißt ich muss irgendwie aus der Form die in der Liste ist, im nachhinein eine Instanz erzeugen.

    VB.NET-Quellcode

    1. Dim f As New ArrayList
    2. Dim c As Form
    3. Dim d As Form
    4. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    5. f.Add(c)
    6. f.Add(c)
    7. End Sub
    8. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    9. d = New f.Item(1)
    10. d.Show()
    11. End Sub



    Das geht ja leider nicht:

    VB.NET-Quellcode

    1. f.Add(new c)
    Ja so wie wir es oben geschrieben haben funktioniert es ja auch, allerdings kann ich das array nicht variabel beschreiben. Ich muss immer die Form direkt in das array einlesen. Ich sucher aber nach einer Möglichkeit das array mittels einer Variablen zu füllen die die Form beinhaltet und danach dann eine Instanz daraus zu bilden. Die Variable als Instanz der Form einlesen geht ja nicht oder?
    Was ich nun noch versucht habe ist folgendes. Ich bin einen anderen Weg gegangen.

    Über den Fensternamen eine Instanz zu erzeugen.

    VB.NET-Quellcode

    1. Shared Sub Form_per_Name_anzeigen(ByVal FormName As String)
    2. ' Erzeugt eine neue Instanz einer Form auf Basis des
    3. ' Klassennamens der Form (z.B. "Form1") und zeigt
    4. ' diese neue Instanz an.
    5. Try
    6. ' Referenz auf die ausgeführte (diese) Assembly holen
    7. Dim myAssembly As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
    8. ' Den Namen der Assembly ermitteln:
    9. Dim strAssemblyName As String = myAssembly.GetName().Name.ToString
    10. ' Den kompletten Namen (inkl. Assemblynamen) des Form-Typs ermitteln
    11. ' (diese Zeile sorgt zudem für Toleranz bzgl. Groß-/Kleinschreibung):
    12. Dim FullName As String = myAssembly.GetType(strAssemblyName & "." & FormName, False, True).ToString
    13. ' Form instanzieren und Formvariable zuweisen
    14. Dim myForm As Form = CType(myAssembly.CreateInstance(FullName), Form)
    15. ' Die erzeugte Instanz anzeige
    16. ' Form aufrufen
    17. Hauptfenster_Form_setzen(myForm, False)
    18. Catch ex As System.NullReferenceException
    19. ' Formname existiert nicht - Standard: Keine Reaktion zeigen.
    20. ' Natürlich können Sie hier auch andere Reaktionen vorsehen.
    21. MessageBox.Show(ex.Message)
    22. Catch ex As Exception
    23. ' Anderer Fehler, Fehlermeldung anzeigen.
    24. MessageBox.Show(ex.Message)
    25. End Try
    26. End Sub



    Es funktioniert auch. Nur manchmal erhalte ich in der Zeile:

    VB.NET-Quellcode

    1. Dim FullName As String = myAssembly.GetType(strAssemblyName & "." & FormName, False, True).ToString


    Eine "NullreferenzException". Aber warum???

    demmy schrieb:

    VB.NET-Quellcode

    1. d = New f.Item(1)
    Überleg doch einfach mal, was da steht:

    VB.NET-Quellcode

    1. Dim dlg2 = New Form2 ' i.O.
    2. Dim dlg3 = new dlg2 ' Nonsens

    Willst Du irgendetwas clonen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    mhh im Grunde könnte man es so bezeichnen. ;) ich weiß nicht wie ich das besser beschreiben soll. Clonen, Kopieren, Instanzieren

    Was ich bräuchte wäre ein Array, indem nicht die Form als solche abgelegt wird, sondern eine Kopie davon. Oder nur die Bezeichnung der Form, mit der ich dann nach dem Auslesen eine Instanz der Form erstellen kann.

    Hintergrund ist, die original Form soll nach dem einlesen in das Array geschlossen werden. Ich will aber über das array zurückverfolgen können, welche Formen in welcher Reihenfolge offen waren und diese über das Array evtl. in umgekehrter Reihenfolge wieder öffnen. Das heißt also Schritt für Schritt zurück gehen bis das array leer ist.
    Das geht aber eben nur wenn ich Instanzen erzeugen kann. Denn ist die Form einmal geschlossen und ich versuche sie über das Array zu holen, bekomme ich die Meldung das auf ein verworfenens Objekt nicht zugegriffen werden kann. Was ja auch Sinn macht.
    Ja genau das soll es werden.

    Mhh das Problem das mehrere Seiten geöffnet sein können habe ich gelöst. Indem immer nur eine Seite geöffnet sein kann und muss! ;) Die aktuelle Seite wird in einem Splitcontainer angezeigt. Wobei die eine Spalte des Containers das Menü beinhaltet und die andere Spalte die aktuelle Seite.

    Die einzelnen Forms sind nur die Bedienoberflächen der einzelnen Menüpunkte, welche beliebig gewechselt werden können. Das eigentliche Programm läuft komplett im Hintergrund in Klassen ab.

    Ich habe das Problem im Moment so gelöst, das ich ein Array mit den Namen der einzelnen Formen fülle und dann aus den Namen eine Instanz der Form erzeuge.

    Es sei denn jemand hat noch eine andere Idee?

    demmy schrieb:

    Wobei die eine Spalte des Containers das Menü beinhaltet und die andere Spalte die aktuelle Seite.
    Wenn die Forms jeweils eine "aktuelle Seite" darstellen sollen, die das ganze Splitterpanel ausfüllt, dann ist imo geraten, statt der Forms UserControls zu nehmen.
    Weil Forms sind drauf konzipiert, verschiebbar zu sein, größenveränderlich und wegklickbar, also Features, die bei einer Seiten-orientierten Anwendung grad unterdrückt werden müssten.
    Oder halt UserControl nehmen, das sind gewissermaßen Forms ohne diese hier störenden Features, genau dazu konzipiert, eingebunden zu werden.
    mhh ok da hast du recht,

    ich habe alledrings bei den Forms die FormBorderStyle-Eigenschaft auf None gesetzt und sie werden mit Dockstyle.Fill
    in das Control geladen.
    Soweit funktioniert das eigentlich ganz gut. Sonst müsste ich jetzt das ganze Projekt wieder umstricken!?

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

    Prinzipiell vertrete ich: Immer sofort umstricken, wenn sich ein angemessener Ansatz eröffnet.
    Meist ist man noch Monate oder Jahre mit dem Projekt beschäftigt, und irgendwann wird man doch umstricken - da kann man es auch gleich machen.

    Im Falle von Form->UserControl kannst du sogar hacken.

    Also zunächst ein Backup machen, etwa mit SolutionExplorer (ist auch egal wie - Hauptsache getestet, dass dus entpacken kannst und läuft auf Anhieb)

    Dann von den umzustrickenden Forms die .Designer.vb öffnen, und die Zeile "Inherits Windows.Forms.Form" ersetzen durch: "Inherits Windows.Forms.Usercontrol"

    Dann gibts noch ein paar FolgeFehler, weil eben UserControl einige Eigenschaften nicht hat, aber die betreffenden Zeilen sind repariert, indem sie schlicht gelöscht wern :D .

    Weitere Fehler können in deinem Code liegen, wenn die Dinger als Form angesprochen werden, wo sie jetzt doch UserControls sind - da wären die entsprechenden Deklarationen anzupassen.

    Aber man kann noch viel mehr umstricken. Guggemol TabControlOhneReiter. So eine Page mit wechselndem Inhalt baue ich standardmäßig aus einem TabControl ohne Reiter auf - in einfachen Fällen ist man mit 4 oder 5 Zeilen Code fertig - der Rest kann äußerst bequem im Designer designed wern.
    OK das werde ich mal testen. Noch eine Frage.
    Werden Usercontrols evtl. Auch schneller geladen als Formen?
    Und kann man Usercontrols Kinderfenster übergeben?

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

    kaum.

    Aber das ist eine Optimierungsfrage, und Optimierungen soll man immer immer hintanstellen. Gugge Rules Of Optimization

    Also bevor das Teil nicht funktional vollkommen i.O. ist, holst du dir mit Optimierungen immer nur Kuckuckseier ins Nest.

    Später kann man überlegen, die UserControls erst dann zu erzeugen, und auf den TabPages aufzubringen, wenn eine Tabpage angewählt wird.
    Oder man machts TabControl doch wieder weg, und packt dynamisch jeweils ein aktuelles UserControl aufs SplitterPanel.
    Aber das muß man halt intelligent verwalten, etwa durch eine List(Of Type), in die man RuntimeTypen reinmacht, die die verschiedenen Ucls beschreiben, und aus denen sie sich erzeugen lassen.
    Sowas ähnliches kannstedir auf MDI-Variationen angugge - in einer Variante mache ich sowas mit den MDI-ChildForms.

    demmy schrieb:

    Werden Usercontrols evtl. Auch schneller geladen als Formen?

    Das klingt so wie
    Werden Buttons schneller geladenn als Formen.
    Das kannst Du Dir selbst beantworten.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!