none
Formular über einen string öffnen RRS feed

  • Frage

  • Hallo,

     

    ich möchte Formulare über einen String öffnen und wieder schießen, hat da jemand eine Idee?

    Vielen Dank im voraus.

    Montag, 24. November 2008 11:39

Antworten

  • Die folgende Funktion durchsucht die aktuelle Assembly nach vorhandenen Formularen. Wenn ein Formular mit dem angegebenem Namen gefunden wurde, wird diese Form neu erzeugt (neue Instanz) und diese zurückgegeben.

     

    Function ShowForm(ByVal FormName As String) As Form

    Dim _myAssembly As System.Reflection.Assembly

    Dim _mytypes As Type()

    Dim _Form As Form = Nothing

    '*** die aktuelle Assembly zuweisen

    _myAssembly = System.Reflection.Assembly.GetExecutingAssembly

    '*** holt sich alle Typen die in der Assembly vorhanden sind

    _mytypes = _myAssembly.GetTypes

    For Each mType As Type In _mytypes

    '*** schauen wir mal nach, ob der aktuelle Typ von der Klasse Form abgeleitet ist

    '*** UND auch den richtigen Namen besitzt

    If mType.BaseType Is GetType(Form) AndAlso mType.Name = FormName Then

    '*** Wenn ja, eine Instanz der Form herstellen

    _Form = Activator.CreateInstance(mType)

    '*** Schleife vorzeitig verlassen

    Exit For

    End If

    Next

    Return _Form

    End Function

     

    Ein Aufruf könnte wie folgt aussehen:

     

    Dim _myForm As Form

    Dim _string As String

     

    '*** z.B.

    _string = "Form2"

     

    '*** suche nach der Form

    _myForm = ShowForm(_string)

     

    '*** Falls die Form gefunden wurde, diese anzeigen

    If Not _myForm Is Nothing Then _myForm.Show()

     

     

     

    Ich hoffe das der Quellcode nachvollziehbar ist und Ihnen weiterhilft.

     

    mfg.

     

    Thomas Vujica

     

    Montag, 8. Dezember 2008 12:28
  • Mit welcher Anweisung wird aus dem _string eine ausführbare Form erzeugt? Ich habe so etwas ähnliches auch versucht.
    Hallo Ellen,

    die Instanz wird mit folgender Anweisung erzeugt:

    _Form = Activator.CreateInstance(mType)

    Vorher werden per Reflection die im Assembly verfügbaren Typen durchlaufen und überprüft, ob der Name des gesuchten Formulars mit dem gefundenen Typnamen übereinstimmt.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Dienstag, 9. März 2010 08:09
  • Hallo Stefan,

    das verwendet man u.a. dann, wenn man seine Anwendung in unabhängige Module aufteilen will.
    Wobei die Technik nicht auf Formulare begrenzt ist, sondern über Reflection auf jeden Aspekt
    ausgedehnt werden kann.
    Ein Stichwort wäre dafür Plugin, siehe z. B.:
    http://forum.vb-paradise.de/allgemeines/tipps-tricks-und-tutorials/allgemein/8747-wie-erstelle-ich-ein-plugin-system-unter-vb-net-framework-2/
    http://www.vbarchiv.net/workshop/workshop_93-erstellen-von-plugins-zum-erweitern-eigener-programme.html

    Gruß Elmar

    Dienstag, 9. März 2010 09:55

Alle Antworten

  • Hallo Michael,

    Was für Formulare möchtest du denn öffnen? Dateien kannst du in der Regel mit einem StreamReader einlesen und mit einem StreamWriter auf die Festplatte speichern. Um Zugang zu den Methoden zu erlangen musst du noch "Imports System.IO" vor deine classe setzten.

    Hilft dir das?

    LG

    Tim
    Montag, 24. November 2008 12:41
  • Hallo Tim,

     

    ich habe mich wahrscheinlich zu pauschal ausgedrückt. Nun, das Problem sieht so aus:

     

    Ich lese eine Menüstruktur aus einer Datenbank ein (Treeview). Klicke ich nun auf einen der Nodes, soll

    sich eine gleichlautende (treeview.selectednodes.text) Form öffnen. 

    treeview.selectednodes.text und Formname sind identisch, aber ich kriege die Kurve nicht vom String zur Form.

     

    LG

     

    Michael

    Montag, 24. November 2008 13:03
  • Ich würde einfach über IF-Elseif-Else abfragen was für ein String das ist und dann das entsprechende Form starten.

    Montag, 8. Dezember 2008 06:14
  • das ist auch nicht mein Problem, sondern

    dim aufzurufendeForm as string

    aufzurufendeForm wird dann als string aus der Datenbank gelesen und ist z.B. "frmBestellungen"

    aufzurufendeForm.show() geht aber nicht?

    wahrscheinlich kleines Problem, aber große Wirkung?
    Montag, 8. Dezember 2008 08:54
  • Die folgende Funktion durchsucht die aktuelle Assembly nach vorhandenen Formularen. Wenn ein Formular mit dem angegebenem Namen gefunden wurde, wird diese Form neu erzeugt (neue Instanz) und diese zurückgegeben.

     

    Function ShowForm(ByVal FormName As String) As Form

    Dim _myAssembly As System.Reflection.Assembly

    Dim _mytypes As Type()

    Dim _Form As Form = Nothing

    '*** die aktuelle Assembly zuweisen

    _myAssembly = System.Reflection.Assembly.GetExecutingAssembly

    '*** holt sich alle Typen die in der Assembly vorhanden sind

    _mytypes = _myAssembly.GetTypes

    For Each mType As Type In _mytypes

    '*** schauen wir mal nach, ob der aktuelle Typ von der Klasse Form abgeleitet ist

    '*** UND auch den richtigen Namen besitzt

    If mType.BaseType Is GetType(Form) AndAlso mType.Name = FormName Then

    '*** Wenn ja, eine Instanz der Form herstellen

    _Form = Activator.CreateInstance(mType)

    '*** Schleife vorzeitig verlassen

    Exit For

    End If

    Next

    Return _Form

    End Function

     

    Ein Aufruf könnte wie folgt aussehen:

     

    Dim _myForm As Form

    Dim _string As String

     

    '*** z.B.

    _string = "Form2"

     

    '*** suche nach der Form

    _myForm = ShowForm(_string)

     

    '*** Falls die Form gefunden wurde, diese anzeigen

    If Not _myForm Is Nothing Then _myForm.Show()

     

     

     

    Ich hoffe das der Quellcode nachvollziehbar ist und Ihnen weiterhilft.

     

    mfg.

     

    Thomas Vujica

     

    Montag, 8. Dezember 2008 12:28
  • sehr gut,  funktoniert!! Vielen Dank.
    Mittwoch, 10. Dezember 2008 12:41
  • Diesen Code habe ich ebenfalls schon länger gesucht ;-)

    Nun hätte ich noch eine Frage: Wie schließe ich eine Form, die ich mittels dieser Funktion aufgerufen habe?
    Sonntag, 7. März 2010 09:52
  • Hallo Michael,

    so wie jedes andere Formular Deiner Anwendung auch, über die passende Objektreferenz. In dem Beispiel wäre das _MyForm.Close(). Innerhalb des Formulars wäre ferner Me.Close() das Mittel der Wahl, um das Formular per Code zu schließen.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Sonntag, 7. März 2010 10:14
  • danke für die schnelle Antwort, jedoch hatte ich noch was vergessen - ich habe die Forms als SDI-Form innerhalb eines MDI-Fensters geöffnet und da läßt sich das SDI-Fenster nicht über _MyForm.close() schließen.

     

    Function ShowForm(ByVal FormName As String, ByVal FormTitle As String) As Form

     

    Dim _myAssembly As System.Reflection.Assembly

     

    Dim _mytypes As Type()

     

    Dim _Form As Form = Nothing

     

    Dim _FormTitle As String = FormTitle

    _myAssembly = System.Reflection.Assembly.GetExecutingAssembly

    _mytypes = _myAssembly.GetTypes

     

    For Each mType As Type In _mytypes

     

    If mType.BaseType Is GetType(Form) AndAlso mType.Name = FormName Then

    _Form = Activator.CreateInstance(mType)

    _Form.MdiParent = MDI_Main

    _Form.MinimizeBox =

    False

    _Form.MaximizeBox =

    False

    _Form.Text = _FormTitle

     

    Exit For

     

    End If

     

    Next

     

    Return _Form

     

    End Function

    Sonntag, 7. März 2010 10:24
  • Hallo Michael,

    bei einem MDI Form kannst Du einfach über das aktuelle MDI Child gehen:

    MDI_Main.ActiveMdiChild.Close()

    Über die MdiChildren Eigenschaft des MDI Formulars hast Du zudem Zugriff auf alle Child Instanzen, die derzeit im MDI Container gehostet werden.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Sonntag, 7. März 2010 11:03
  • Danke ;-) hätte ich ja auch drauf kommen können...
    Sonntag, 7. März 2010 11:07
  • Ich habe jetzt aber ein anderes Problem.

    Mithilfe der o.g. Funktion habe ich ein Fenster innerhalb eines MDI-Containers geöffnet. Ich wechsel nun per Code in ein anderes Fenster. In diesem Fenster befindet sich ein Link zu einem Fenster, welches ich mit der o.g. Funktion wieder öffnen möchte. Nun wird natürlich eine weitere Kopie des Fensters erstellt. Ich möchte aber, dass ein bereits bestehendes Fenster geöffnet wird und wenn es nicht vorhanden ist, erst dann neu erstellt wird.

    Könntet ihr mir nochmal eine Hilfestellung geben?
    Montag, 8. März 2010 21:37
  • Hallo Michael,

    zwei Möglichkeiten: Du hinterlegst in der Tag-Eigenschaft Deiner geöffneten Formular eine eindeutige Kennung. Über die MdiChildren Eigenschaft iterierst Du durch alle MDI Childs und fragst diese Tag Eigenschaft ab, ob sie dem gesuchten Wert entspricht. Trifft das zu, hast Du Dein Formular.

    Alternative: Du pflegst die Referenzen Deiner erzeugten Formulare in einem Dictionary. Als Schlüssel dient hier entweder der Formularname, wenn jedes Formular tatsächlich einmal vorhanden sein darf oder ein frei festlegbarer Schlüssel.

    Grobes Beispiel:

    Public Class MDI_Main
      Private m_MdiChilds As New Dictionary(Of String, Form)
      
      Public Function GetFoo() As Form
        Dim lMyForm As Form 
    	
        If m_MdiChild.ContainsKey("Foo") Then
    	  lMyForm = m_MdiChild.Item("Foo")
    	
    	Else
              lMyForm = ShowForm("frmFoo", "Foo")
    	
    	  m_MdiChild.Add("Foo", lMyForm)
    	End If
    	
    	Return lMyForm
      End Sub
    End Class


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Montag, 8. März 2010 21:56
  • Hallo Vujico,

    ich habe eine Frage dazu.

    Mit welcher Anweisung wird aus dem _string eine ausführbare Form erzeugt? Ich habe so etwas ähnliches auch versucht. Das ist gründlich schief gegangen.


    Dann hätte ich noch einen alternativen Vorschlag zu machen.
    Öffnen eines Formulars nicht über den String, sondern über einen Index.

    Das würde so aussehen:

    Dim _myForms as New List(Of Form)
    
    Dim Index = 1
    
    ' Liste versorgen
    _myForms.Add(form2)
    
    
    ' Form starten über index
    if NOT _myForms(index) is Nothing then _myForms(index).Show()
    
    
    was haltet Ihr davon
    schöne Grüsse
    Ellen


    Dienstag, 9. März 2010 06:59
  • Hallo,

    vermutlich bin ich nicht tief genug drin in der Materie.
    Wenn ich eine Form öffnen möchte nutze ich Form.Show() und zum Schließen Me.Close().
    Welchen Vorteil bietet mir die Methode, die hier besprochen wird?

    LG
    Stefan
    Liebe Grüße Stefan
    Dienstag, 9. März 2010 07:05
  • Hallo Stefan,
    so etwas nennt man, glaube ich, späte Bindung.
    Die Festlegung welches Formular geöffnet wird geschieht nicht beim
    Programmieren, sondern erst zur Laufzeit. In diesem Beispiel kommen
    die Daten ja aus einer Datenbank. Die Daten entstehen erst im Programm
    und nicht wenn Du programmierst.
    OK, man kann das hier alles umgehen mit jeder Menge if then else Abfragen. 
    Aber das hier ist eleganter.

    Ich habe so was ähnliches geschrieben, wo Controls zur Laufzeit dynamisch erzeugt werden.
    das macht wirklich Sinn. Schau Dir das mal an
    http://social.msdn.microsoft.com/Forums/de-DE/visualbasicde/thread/0e994166-2ed8-4a8e-af20-605a83c18111

    schöne Grüße
    Ellen
    Dienstag, 9. März 2010 07:16
  • Mit welcher Anweisung wird aus dem _string eine ausführbare Form erzeugt? Ich habe so etwas ähnliches auch versucht.
    Hallo Ellen,

    die Instanz wird mit folgender Anweisung erzeugt:

    _Form = Activator.CreateInstance(mType)

    Vorher werden per Reflection die im Assembly verfügbaren Typen durchlaufen und überprüft, ob der Name des gesuchten Formulars mit dem gefundenen Typnamen übereinstimmt.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Dienstag, 9. März 2010 08:09
  • Hallo Stefan,

    das verwendet man u.a. dann, wenn man seine Anwendung in unabhängige Module aufteilen will.
    Wobei die Technik nicht auf Formulare begrenzt ist, sondern über Reflection auf jeden Aspekt
    ausgedehnt werden kann.
    Ein Stichwort wäre dafür Plugin, siehe z. B.:
    http://forum.vb-paradise.de/allgemeines/tipps-tricks-und-tutorials/allgemein/8747-wie-erstelle-ich-ein-plugin-system-unter-vb-net-framework-2/
    http://www.vbarchiv.net/workshop/workshop_93-erstellen-von-plugins-zum-erweitern-eigener-programme.html

    Gruß Elmar

    Dienstag, 9. März 2010 09:55
  • Hallo Thorsten,

    ich habe deinen Code eingefügt und ihn ein wenig abgewandelt. Jetzt bekomme ich aber eine Exception, dass der Schlüssel bereits vergeben ist. An welcher Stelle wechsele ich zu einem bereits geöffneten Formular?

    Mein Wunsch ist es doch nur eine SDI-Form per String aufrufen zu können (was ja jetzt geht) und zu dieser SDI-Form wechseln können, wenn diese bereits geladen ist.

     

    Dim lMyForm As Form

     

    If m_MdiChilds.ContainsKey(FormTitle) Then

    lMyForm = m_MdiChilds.Item(FormTitle)

     

    Else

    lMyForm = ShowForm(FormName, FormTitle)

    m_MdiChilds.Add(FormName, lMyForm)

     

    End If

     

    Return lMyForm

    Dienstag, 9. März 2010 21:39
  • Hallo Michael,

    es wäre von Vorteil, wenn Du auch überall den gleichen Schlüssel für das Dictionary verwenden würdest. Aktuell prüfst Du ob der FormTitle bereits im Dictionary vorhanden ist, fügst aber den FormName als Schlüssel hinzu. Kein Wunder also, dass Du so Duplikate bekommst, denn ContainsKey kann niemals True sein.

    Dim lMyForm As Form
    
    If m_MdiChilds.ContainsKey(FormTitle) Then
    
       lMyForm = m_MdiChilds.Item(FormTitle)
    
    Else
    
       lMyForm = ShowForm(FormName, FormTitle)
    
       m_MdiChilds.Add(FormTitle, lMyForm)
    
    End If
    
    Return lMyForm

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Mittwoch, 10. März 2010 17:11
  • Hallo Thorsten,

    danke für den Hinweis.

    Jetzt wird immerhin keine Kopie mehr erstellt und geöffnet. Aber das bereits geöffnete SDI-Formular wird auch nicht geöffnet. Keine Reaktion.

    Grüße
    Michael
    Mittwoch, 10. März 2010 17:44
  • Hallo Michael,

    Du musst das Formular noch in den Vordergrund holen, durch Aufruf von

    lMyForm.BringToFront()

    Thorsten Dörfler
    Microsoft MVP Visual Basic
    Mittwoch, 10. März 2010 18:05
  • PERFEKT

    1000000 Dank
    kann jetzt endlich weiterarbeiten ;-)

    Ich habe noch eine zusätzliche Function anlegen müssen und zwar für den Fall, man schließt das SDI-Formular und möchte es später wieder öffnen:

    Public

     

    Function DeleteFoo(ByVal FormTitle As String) As Form

     

    Dim dMyForm As Form

     

    If m_MdiChilds.ContainsKey(FormTitle) = False Then

     

    Exit Function

     

    Else

    dMyForm = m_MdiChilds.Item(FormTitle)

    m_MdiChilds.Remove(FormTitle)

     

    End If

     

    Return dMyForm

     

    End Function

    Mittwoch, 10. März 2010 18:09