Korrektes löschen eines Controls [WinForms]

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von wolfi_bayern.

    Korrektes löschen eines Controls [WinForms]

    Hallo,

    hatte gerade das Problem dass beim Löschen von Controls per "For each" nicht alle Controls gelöscht wurden.
    Nach kurzer Recherche im Forum fand ich einen Beitrag, in dem gesagt wurde dass löschen von Controls per "For Each" problematisch sein.
    Nun würde ich gern wissen warum das so ist, da ich bei einem anderen "For Each" Löschvorgang keine Probleme hatte.

    Problematisch:

    VB.NET-Quellcode

    1. For Each t As TabPage In tabCtrl.TabPages
    2. For Each c As Control In t.Controls
    3. c.Dispose()
    4. Next
    5. Next


    Vorher:


    Nachher:


    Nicht problematisch:

    VB.NET-Quellcode

    1. ​For Each t As TabPage In tabCtrl.TabPages
    2. t.Dispose()
    3. Next


    Vorher:


    Nachher:


    Im Endeffekt wird ja bei beiden Malen eine Liste durchgegangen und bei jedem Durchgang wird 1 Control daraus entfernt.

    PS: Entschuldigt bitte die Quellcode-Formatierung, keine Ahnung was da schiefgegangen ist...
    Danke schon einmal für die Antwort, aber das wurde in dem anderen Thread schon erklärt.
    Ich verstehe nur nicht warum es bei der einen Liste funktioniert, jedoch bei der anderen nicht.
    Nur um genauer auf die Listen einzugehen, bei

    VB.NET-Quellcode

    1. For Each t As TabPage In tabCtrl.TabPages
    2. For Each c As Control In t.Controls
    3. c.Dispose()
    4. Next
    5. Next


    enthält c beim ersten Durchlauf der ersten Schleife 22 Elemente. Beim Debuggen ist zu sehen, dass jedoch wird scheinbar gezielt bei jedem Durchlauf jedes 2. Control (Labels) übersprungen wird.
    Bei der anderen Schleife passiert es nicht.

    nicerdicer schrieb:

    Ich verstehe nur nicht warum es bei der einen Liste funktioniert, jedoch bei der anderen nicht.
    Poste mal den Code für beide Listen.
    @VB1963 Ein Dispose-stes Control ist ja noch Mamber der Liste.
    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!

    RodFromGermany schrieb:

    Ein Dispose-stes Control ist ja noch Mamber der Liste.

    VB.NET-Quellcode

    1. Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    2. Debug.WriteLine(Me.Controls.Count - 1)
    3. For Each _e In Me.Controls
    4. Debug.WriteLine(_e.name)
    5. _e.dispose
    6. Next
    7. 'For i = Me.Controls.Count - 1 To 0 Step -1
    8. ' Debug.WriteLine(String.Format("{0}-{1}", i, Me.Controls(i).Name))
    9. ' Me.Controls(i).Dispose()
    10. 'Next
    11. Debug.WriteLine(Me.Controls.Count - 1)
    12. End Sub
    Fülle einmal einige verschiedene Controls per Designer in die Form und führe obigen Code aus...
    Da wirst du sehen, dass nicht alle verschwinden. Beim auskommentierten Codeteil passiert das schon - das meinte ich...
    @VB1963 OHa.
    Aber üblicherweise, wie Du schon schriebst, werden die Items der Liste von hinten gelöscht, removed und feddich.
    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!
    Die Datentypen der Collections, deren Elemente disposed werden, sind unterschiedlich.

    Von ControlCollection her weiss ich, dass die ein Element autom. entfernt, wenn es disposed wird. Das erklärt (ansatzweise), warum nur jedes 2. Control "erwischt" wird.
    Ansatzweise deshalb, weil eiglich müsste es eine Exception geben, weil innerhalb ForEach ist nicht zulässig, dass Elemente entfernt werden.

    Die annere Collection - guck mal den Datentyp nach - verhält sich offensichtlich anders.

    Wie dem auch sei: Code sauber, indem du
    die Controls erst in ein Array einliest.
    Dann rückwärtslaufend aus ihrer Auflistung entfernst, mit .RemoveAt(index)
    Dann alle Array-Elemente disposen.

    Das nenne ich sauber, weil wie gesagt ControlCollection verhält sich eigentümlich, wenn in ihr Elemente disposed werden. Und ob die annere sauber tickt, ist eben nicht gewiss (lässt sie etwa disposete Tabpages drinne?).

    Hier - probierma die Exception, die kommt, wenn aus einer "vernünftigen" Auflistung mit Foreach was gelöscht wird:

    VB.NET-Quellcode

    1. Private Sub ForEachRemove()
    2. Dim numbs = Enumerable.Range(0, 10).ToList
    3. For Each numb In numbs
    4. numbs.Remove(numb)
    5. Next
    6. End Sub

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