Rekrsive Schlefe um alle Controls einer Form zu "sammeln"

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Luchshot.

    Rekrsive Schlefe um alle Controls einer Form zu "sammeln"

    Nabend,

    Ich würde gerne alle Controls meiner Form die der Benutzer ändern kann auflisten, auch wenn sie in anderen Containern verborgen sind.

    Ich habe dafür folgenden Code entwickelt der allerdings leider keine Funktion aufweist.^^

    VB.NET-Quellcode

    1. Private Sub ComandListe(ByVal Container As Object)
    2. If TypeOf Container Is Form Then
    3. Dim form As Form = DirectCast(Container, Form)
    4. For Each con As Control In form.Controls
    5. If TypeOf con Is Panel Then
    6. ComandListe(con)
    7. End If
    8. If TypeOf con Is GroupBox Then
    9. ComandListe(con)
    10. End If
    11. Next
    12. End If
    13. If TypeOf Container Is Panel Then
    14. Dim Panel As Panel = DirectCast(Container, Panel)
    15. For Each con As Control In Panel.Controls
    16. If TypeOf con Is Panel Then
    17. ComandListe(con)
    18. End If
    19. If TypeOf con Is GroupBox Then
    20. ComandListe(con)
    21. End If
    22. Next
    23. End If
    24. If TypeOf Container Is GroupBox Then
    25. Dim GpB As GroupBox = DirectCast(Container, GroupBox)
    26. For Each con As Control In GpB.Controls
    27. If TypeOf con Is Panel Then
    28. ComandListe(con)
    29. End If
    30. If TypeOf con Is GroupBox Then
    31. ComandListe(con)
    32. End If
    33. Next
    34. End If
    35. If TypeOf Container Is TextBox Then
    36. Dim Objekt As TextBox = DirectCast(Container, TextBox)
    37. ControlList.Add(Objekt)
    38. ComboBox1.Items.Add(Objekt.Name)
    39. End If
    40. If TypeOf Container Is ComboBox Then
    41. Dim Objekt As ComboBox = DirectCast(Container, ComboBox)
    42. ControlList.Add(Objekt)
    43. ComboBox1.Items.Add(Objekt.Name)
    44. End If
    45. If TypeOf Container Is CheckBox Then
    46. Dim Objekt As CheckBox = DirectCast(Container, CheckBox)
    47. ControlList.Add(Objekt)
    48. ComboBox1.Items.Add(Objekt.Name)
    49. End If
    50. If TypeOf Container Is RadioButton Then
    51. Dim Objekt As RadioButton = DirectCast(Container, RadioButton)
    52. ControlList.Add(Objekt)
    53. ComboBox1.Items.Add(Objekt.Name)
    54. End If
    55. If TypeOf Container Is NumericUpDown Then
    56. Dim Objekt As NumericUpDown = DirectCast(Container, NumericUpDown)
    57. ControlList.Add(Objekt)
    58. ComboBox1.Items.Add(Objekt.Name)
    59. End If
    60. End Sub


    Der sub wird im FormLoad Event aufgerufen.

    VB.NET-Quellcode

    1. ComandListe(Me)


    Die Liste ist selbstverständlich deklariert.
    Es tritt auch keine Fehlermeldung auf.
    Nabend nochmals,
    Ich finde es ja echt gut das Mir geholfen wurde, aber trotzdem würde ich gerne wissen wieso Mein Code nicht funktioniert.
    Es geht mir darum, dass ich das Problem verstehe nich darum einen laufenden Code zu haben.

    Fals mir jemand sagen kann was ich an meinem Code ändern muss wäre ich darüber sehr dankbar.
    Hi
    es gibt auch eine einfachere Methode:

    VB.NET-Quellcode

    1. Private Shared Function ListControls(ByVal control As Control) As IEnumerable(Of Control)
    2. Dim ctrl As IEnumerable(Of Control) = control.Controls.Cast(Of Control)()
    3. Return ctrl.Concat(ctrl.SelectMany(AddressOf ListControls))
    4. End Function

    wenn man dann noch filtern möchte, kann man das entweder mit einem schwierigeren Ausdruck machen oder einfach per If-Abfrage.
    Zum enumerieren könnte man folgenden Code verwenden:

    VB.NET-Quellcode

    1. For Each c As Control In ListControls(Me)

    Dein Code hat einige Schwachstellen.
    1. frägst du immer auf konkrete Typen ab. Label, Form, Button, etc. haben aber einen gemeinsamen Basistypen. Dieser Basistyp heißt Control. Jedes Control kann weitere Controls enthalten, muss es aber nicht. Wähle daher einfach den Typ Control statt alle über TypeOf <value> Is <type> abzufragen.
    2. stelle dir folgende Situation vor: Du hast einen Button Button1 in einem Panel Panel1 in einer Form (Me) und rufst CommandListe(Me) auf. Erst wird jedes Control der Form durchgegangen und überprüft, ob es ein Panel ist und danach, ob es eine GroupBox ist. Wenn dies jeweils der Fall ist, wird für beide die Methode erneut aufgerufen. D.h. bei Panel1 wird die Methode wieder aufgerufen. Anschließend wird der Code in Zeile 13ff. aufgerufen. Hier ist der Hund drin: Es werden alle Controls durchgegangen, aber dann überprüft, ob das Control ein Panel oder eine GroupBox ist. Klar, für jeweilge Controls wird die Methode aufgerufen, aber für die restlichen nicht. Wenn jetzt eine TextBox erreicht wird, wird einfach mit dem nächsten Control fortgefahren. Da aber nur die Form und Panels oder GroupBoxen enumeriert werden, werden die anderen Abfragen niemals erreicht.
    Gibt noch paar andere Mankos, aber ich denke mal, das reicht für den Anfang.

    Gruß
    ~blaze~
    ou mann, danke jetzt wo Dus sagst wirds Mir deutlich....

    ich habe zwar abgefragt ob es ein Container ist oder nicht aber mein Sub wird nie mit einem wirklichem Steuerelement aufgerufen.

    danke hast mir sehr weiter geholfen.

    habe es nun so gelöst wie "nafets3646" es vorgeschlagen hat mit einer kleinen änderung.

    VB.NET-Quellcode

    1. 'Commands der form auflisten
    2. Public Sub TranslateForm(ByRef frm As Form)
    3. For Each cntrl As Control In frm.Controls
    4. Me.TranslateControl(cntrl)
    5. Next
    6. End Sub
    7. Private Sub TranslateControl(ByRef cntrl As Control)
    8. If cntrl.Name.Length > 2 Then
    9. ControlList.Add(cntrl)
    10. End If
    11. For Each item As System.Windows.Forms.Control In cntrl.Controls
    12. Me.TranslateControl(item)
    13. Next
    14. End Sub


    Die If abfrage Der Namenslänge habe ich aufgrund einer Fehlfunktion eingebunden, bei der manchmal Controls aufgelistet wurden die gar nicht existierten und zwar immer direkt nach NumericUpDown Bausteinen. Warum dies so ist weiß ich nicht.

    Also nochmals DANKE an euch Beiden für die Lösung meines Problems und für die erklärung meines Fehlers.

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