none
Mehrere Instanzen eines Formulars programmatisch schliessen RRS feed

  • Frage

  • Hallo zusammen,

    der code zeigt, wie man mehrere Formulare mit unterschiedlichen Dateninhalten öffnen kann. Nun möchte ich die alle mit einem Button schliessen können. Dazu muss ich aber die Instanzen haben. Dieses wird nicht gehen: frmobject.Close(). Gibt es eine Möglichkeit alle Instanzen zur Laufzeit zu bestimmen?

    schöne Grüsse Ellen

        '
        ' MenuestripView rechte Mousetaste Fahrzeugdaten anz. 
        '
        Private Sub mnViewProdata_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnViewProdata.Click
            If currentPid Like "#######" Then
                Dim frmobject As New dlgProData
                If currentProdata.IsNotNothingOrEmptyOrDbNull Then
                    frmobject.ProData = currentProdata
                    frmobject.Show()
                Else
                    MsgBox("Keine Daten für " & currentPid & " gefunden!")
                End If
            Else
                MsgBox("Kennnummer " & currentPid & " ungültig!")
            End If
        End Sub
    

     


    Ich benutze/ I'm using VB2008 & VB2010
    Freitag, 18. November 2011 16:09

Antworten

  • Hallo Ellen,

    entweder speicherst Du die eröffneten Formulare in einer eigenen List(Of Form),
    Oder aber Du verwendest die Application.OpenForms, wo Du dann auf den Typen testen müsstest.

    Variante 3: Du verwendest die OwnedForms Eigenschaft, was allerdings bedingt,
    dass Du den Owner setzt (oben nicht der Fall).

    Gruß Elmar

    • Als Antwort markiert Ellen Ramcke Samstag, 19. November 2011 12:22
    Freitag, 18. November 2011 16:31
    Beantworter
  • Hallo Ellen,

    naja, ich hatte gerade mal reingeguckt.

    Wie alle Enumeratoren mag es auch der von OpenForms nicht, wenn die Auflistung verändert wird,
    wenn er durchlaufen wird - was hier indirekt durch das Schließen des Formulars passiert.

    Das einfachste ist hier LINQ zu bemühen, um die Formularinstanzen zuvor in ein eigenes Array zu kopieren:

    Dim formsToClose = Application.OpenForms.OfType(Of frmEditData)().ToArray()
    For Each form In formsToClose 
    	form.Close()
    Next
    
    

    OfType() dient hier als einfacher Filter, bei Bedarf kannst Du den Ausdruck erweitern.

    Gruß Elmar

    Freitag, 18. November 2011 18:02
    Beantworter

Alle Antworten

  • Hallo Ellen,

    entweder speicherst Du die eröffneten Formulare in einer eigenen List(Of Form),
    Oder aber Du verwendest die Application.OpenForms, wo Du dann auf den Typen testen müsstest.

    Variante 3: Du verwendest die OwnedForms Eigenschaft, was allerdings bedingt,
    dass Du den Owner setzt (oben nicht der Fall).

    Gruß Elmar

    • Als Antwort markiert Ellen Ramcke Samstag, 19. November 2011 12:22
    Freitag, 18. November 2011 16:31
    Beantworter
  • Hallo Elmar,

    Du bist ja schnell... Application.Openforms ist schon der richitge Weg. Habs getestet:

          Dim frms As FormCollection = Application.OpenForms
            For Each fm As Form In frms
                If TypeOf fm Is frmEditData Then
                    fm.Close()
                End If
    

    Eine Kleinigkeit noch. Wie kann ich dann schliessen?

    Gruss Ellen


    System.InvalidOperationException wurde nicht behandelt.
      Message="Die Auflistung wurde geändert. Der Enumerationsvorgang kann möglicherweise nicht ausgeführt werden."
      Source="mscorlib"
      StackTrace:
           bei System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
           bei ecosView.frmEcosViewMain.Button1_Click(Object sender, EventArgs e) in C:\Dokumente und Einstellungen\iernie\Eigene Dateien\Visual Studio 2008\Projects\ecosView20111118\ecosView\frmEcosViewMain.vb:Zeile 643.
           bei System.Windows.Forms.Control.OnClick(EventArgs e)
           bei System.Windows.Forms.Button.OnClick(EventArgs e)
           bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
           bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
           bei System.Windows.Forms.Control.WndProc(Message& m)
           bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
           bei System.Windows.Forms.Button.WndProc(Message& m)
           bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
           bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
           bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
           bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
           bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
           bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
           bei System.Windows.Forms.Application.Run(ApplicationContext context)
           bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
           bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
           bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
           bei ecosView.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:Zeile 81.
           bei System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
           bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           bei System.Threading.ThreadHelper.ThreadStart()
      InnerException:
    


    Ich benutze/ I'm using VB2008 & VB2010
    Freitag, 18. November 2011 17:02
  • Versuche mal

      For Each f As frmEditData In Application.OpenForms.OfType(Of frmEditData)().ToList()

         f.Close()

      Next

    Setzt .NET 3.5 oder 4.0 voraus (LINQ)


    MVP Data Platform Development My blog
    Freitag, 18. November 2011 18:01
  • Hallo Ellen,

    naja, ich hatte gerade mal reingeguckt.

    Wie alle Enumeratoren mag es auch der von OpenForms nicht, wenn die Auflistung verändert wird,
    wenn er durchlaufen wird - was hier indirekt durch das Schließen des Formulars passiert.

    Das einfachste ist hier LINQ zu bemühen, um die Formularinstanzen zuvor in ein eigenes Array zu kopieren:

    Dim formsToClose = Application.OpenForms.OfType(Of frmEditData)().ToArray()
    For Each form In formsToClose 
    	form.Close()
    Next
    
    

    OfType() dient hier als einfacher Filter, bei Bedarf kannst Du den Ausdruck erweitern.

    Gruß Elmar

    Freitag, 18. November 2011 18:02
    Beantworter
  • Hallo Elmar,

    Dein Code funktioniert perfekt. Ich staune immer wieder was NET alles so bietet. Die Lösung mit einer List(of Form) auf Klassenebene hätte den Nachteil, dass Du sowohl die Forms schliessen und noch die Liste verwalten müsstest. Aber so ist das gut.

    Ich habe experimentiert und bin noch auf eine alternative Lösung gekommen:

           Dim fm As Form = Application.OpenForms("frmEditData")
            Do While fm IsNot Nothing
                fm.Close()
                fm = Application.OpenForms("frmEditData")
            Loop
    

    Vielen Dank und schöne Grüsse Ellen


    Ich benutze/ I'm using VB2008 & VB2010
    Samstag, 19. November 2011 12:22