Autor Beitrag
mocede
Hält's aus hier
Beiträge: 7

Windows 7
C# (VS 2010 #Express )
BeitragVerfasst: Mo 29.12.14 19:29 
Hallo,

ich möchte in einer WPF Anwendung mehrere Textboxen innerhalb einer Groupbox leeren.

Sicherlich kann man jetzt jede Textbox einzeln wie folgt leeren:

ausblenden C#-Quelltext
1:
2:
3:
txt_1.Clear();
txt_2.Clear();
...


Hierbei ergibt sich aber das Problem, dass dies bei besonders vielen Textboxen den Quelltext aufbläht. Schöner wäre da eine ausgereiftere Lösung.

Auf der Suche im Netz habe ich mehrere Lösungen gefunden, die alle grundlegend erstmal gleich aussehen. Die ergoogelte Lösung sieht wie folgt aus:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
     
private void btn_Clear_Click(object sender, RoutedEventArgs e)
     {
          ClearTextBoxes(this.Controls);
     }

private void ClearTextBoxes(Control.ControlCollection cc)
     {
           foreach (Control ctrl in cc)
           {
                TextBox tb = ctrl as TextBox;

                if (tb != null)
                    tb.Text = "";
                else
                    ClearTextBoxes(ctrl.Controls);
            }
        }



Mein Problem ist, dass ich die Lösung an den entscheidenten Punkten nicht verstehe und sie darum auch nicht zum Laufen bekomme.

Mir ist klar, dass ich beim Klick auf den Button btn_Clear die Methode zum Löschen der Textboxen names ClearTextBoxesaufrufe. Doch was ist Control.ControlCollection cc für ein Übergabeparameter?
In der Methode starte ich nun eine foreach-Schleife, welche mir die Textboxen "" setzt, sofern diese nicht leer sind. Doch was hat es mit der Schleifenbedingung (Control ctrl in cc) auf sich? Und was bedeuted das hier genau:
ausblenden C#-Quelltext
1:
TextBox tb = ctrl as TextBox;					


Beim Compilieren bekomme ich die Fehlermeldung "Der Typname 'ControlCollection' ist im Typ 'System.Windows.Controls.Control" nicht vorhanden"
Das sollte doch aber bei Einbinden von System.Windows.Controls; mittels using der Fall sein, oder?

Kann mir jemand bitte helfen den Quelltext zum Laufen zu bekommen?


Moderiert von user profile iconTh69: Topic aus C# - Die Sprache verschoben am Mo 29.12.2014 um 20:10
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Mo 29.12.14 21:03 
Hallo,

also die ControlCollection kommt meines wissens aus WinForms, deshalb kannst du sie auch nicht in WPF verwenden. Du könntest statt dessen UIElementCollection oder ein Root Element, z.B. Panel benutzen.

Dann sähe der Code so aus:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
        private void ClearTextBoxes(Panel rootElement)
        {
            if (rootElement == nullreturn;

            foreach (UIElement el in rootElement.Children)
            {
                TextBox tb = el as TextBox;

                if (tb != null) tb.Clear();
                else ClearTextBoxes(el as Panel);
            }
        }


Das Schlüsselwort as führt dabei eine Konvertierung in den Zieldatentyp durch (im ersten Fall wäre der Zieldatentyp TextBox, im Zweiten Panel). Kann das Objekt nicht konvertiert werden, wird null zurück gegeben.
Der else-Block enthält eine Rekursion. So wird sichergestellt, dass alle weiteren Unterelemente auch gelöscht werden, wenn sie TextBoxen sind.
Sagen wir du hast so eine Struktur:
ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
    <Grid Name="RootGrid">
        <TextBox />
        <TextBox />
        <Grid Name="SubGrid">
            <TextBox />
            <TextBox />
        </Grid>
    </Grid>

ausblenden C#-Quelltext
1:
ClearTextBoxes(RootGrid);					

dann sorgt die Rekursion dafür, dass auch die TextBoxen in SubGrid gelöscht werden.

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler

Für diesen Beitrag haben gedankt: mocede
mocede Threadstarter
Hält's aus hier
Beiträge: 7

Windows 7
C# (VS 2010 #Express )
BeitragVerfasst: Di 30.12.14 00:50 
Hallo C#,

danke für deine Antwort! In der Tat löst dein Code mein Problem, vielen Dank dafür!

Ich glaube von alleine hätte ich das niemals hinbekommen. Einhundertprozentig verstehe ich zwar immer noch nicht was da passiert, aber in diesem Fall geb ich mich mal damit zufrieden das es funktioniert. Leider fehlt mir der Hintergrund zu diesen Panel und UIElementen.

Was mir allerdings auffällt ist, dass das Leeren der TextBoxen nur klappt, wenn diese von bestimmten Steuerelementen "ummantelt" sind, korrekt? Wenn ich den Namen einer GroupBox angebe, klappt das Leeren nicht mehr. Stackpaneles sind dagegen kein Problem. Der Compiler sagt mir, dass ein Problem mit der Konvertierung vorliegt.

Lösen sollte sich das im Falle eines Falles eigentlich ziemlich einfach, indem ich bei solchen Problemen einfach nochmal ein zusammenfassendes, quasi unsichtbares Grid ziehe und dieses dann halt über deine Methode leeren lasse...

Vielen Dank für deine Hilfe!
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Di 30.12.14 01:31 
Hallo,

kein Problem. Ich habe die Methode nochmal etwas abgeändert, sodass es jetzt auch mit der GroupBox geht:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
        private void ClearTextBoxes(UIElement rootElement)
        {
            if (rootElement == nullreturn;

            Panel panel = rootElement as Panel;
            ContentControl cc = rootElement as ContentControl;

            if (panel != null)
            {
                foreach (UIElement el in panel.Children)
                {
                    TextBox tb = el as TextBox;

                    if (tb != null) tb.Clear();
                    else ClearTextBoxes(el);
                }
            }
            else if (cc != null)
            {
                TextBox tb = cc.Content as TextBox;

                if (tb != null) tb.Clear();
                else ClearTextBoxes(cc.Content as UIElement);
            }
        }

Im Prinzip funktioniert das ganze so:
Zuerst wird versucht, dass übergebene UIElement weiter zu spezifizieren, sodass man auf die Children- oder Content-Eigenschaft zugreifen kann. Anschließend wird geprüft, ob das entsprechende Child bzw. der entsprechende Content eine TextBox ist. Ist das der Fall, wird die TextBox geleert. Wenn das nicht der Fall ist, ruft die Methode sich selbst auf (ClearTextBoxes(el); bzw. ClearTextBoxes(cc.Content as UIElement);). Das führt dazu, dass dann die Kinder des UIElements (Children) auch nochmal untersucht werden. So findet man auch TextBoxen, die z.B. in 4 Panels verschachtelt sind.

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler