Zum Finden oder Ansprechen aller Label in einer Form genügt ja eine Schleife über die Controls-Property des Parents:
Befindet sich auf der Form ein TabControl mit mehreren Tabs, auf denen ebenfalls alle Labels erwischt werden sollen, müssen wir mit Rekursion arbeiten.
Ich hab da mal auf Stackoverflow eine Vorlage gefunden, kann aber leider die Quelle nicht mehr finden:
Auflisten aller Labels auf der Form
Nun wollen wir gezielt unsere meigenen UserControls ansprechen.
Das ist im wesentlichen derselbe Code, nur dass wir in der static Prozedur
Aufsammeln aller Objekte, die vom Type type abgeleitet sind
Als Letztes sammeln wir alle Objekte auf, die ein gemeinsames Interface implementieren.
Der Code ist wie der letzte, nur verwenden wir eine auf Interfaces zugeschnittene Extension:
Aufsammeln aller Objekte, die das Interface interf implementieren
Als Abschluss noch die Extensions:
Extensions
Beim Testen hat mich das Studio 2019 überrascht, dass dort eine Reihe von Casts automatisiert werden.
Im Teil mit den Interfaces habe ich das übernommen, bei den Basisklassen nicht, dort kam dieser Vorschlag:
Und für alle, die den Code nicht kopieren wollen, die komplette Solution:
WindowsFormsApp2.zip
Befindet sich auf der Form ein TabControl mit mehreren Tabs, auf denen ebenfalls alle Labels erwischt werden sollen, müssen wir mit Rekursion arbeiten.
Ich hab da mal auf Stackoverflow eine Vorlage gefunden, kann aber leider die Quelle nicht mehr finden:
C#-Quellcode
- /// <summary>
- /// Auflisten aller Labels auf der Form,
- /// auch aus Child-Controls
- /// </summary>
- private void button1_Click(object sender, EventArgs e)
- {
- IEnumerable<Control> c = GetAllType(this, typeof(Label));
- // was damit tun:
- //MessageBox.Show("Total Controls: " + c.Count());
- foreach (Label lbl in c)
- {
- lbl.Text = "bla";
- }
- }
- /// <summary>
- /// alle Objekte aufsammeln, deren aktuelle Instanz vom Type type ist
- /// </summary>
- /// <param name="control">das Parent-Control</param>
- /// <param name="type">der Ziel-Type</param>
- /// <returns>Auflistung der Controls</returns>
- private static IEnumerable<Control> GetAllType(Control control, Type type)
- {
- // alle Controls aufsammeln
- IEnumerable<Control> controls = control.Controls.Cast<Control>();
- // aus dieser nur die Ziel-Controls zurückgeben
- return controls.SelectMany(ctrl => GetAllType(ctrl, type))
- .Concat(controls)
- .Where(c => c.GetType() == type);
- }
Nun wollen wir gezielt unsere meigenen UserControls ansprechen.
Das ist im wesentlichen derselbe Code, nur dass wir in der static Prozedur
GetType()
durch eine Extension ersetzen müssen:C#-Quellcode
- /// <summary>
- /// Auflisten aller von UserControl abgeleiteten Controls auf der Form
- /// </summary>
- private void button2_Click(object sender, EventArgs e)
- {
- IEnumerable<Control> c = GetAllClasses(this, typeof(UserControl));
- // was damit tun:
- MessageBox.Show("Total UserControls: " + c.Count());
- foreach (UserControl ctrl in c)
- {
- UserControl1 ctrl1 = ctrl as UserControl1;
- UserControl2 ctrl2 = ctrl as UserControl2;
- if (ctrl1 != null) { ctrl1.SetText(); }
- if (ctrl2 != null) { ctrl2.SetText(); }
- }
- }
- /// <summary>
- /// alle Objekte aufsammeln, die vom Type type abgeleitet sind
- /// </summary>
- /// <param name="control">das Parent-Control</param>
- /// <param name="cls">der Ziel-Type</param>
- /// <returns>Auflistung der Controls</returns>
- private static IEnumerable<Control> GetAllClasses(Control control, Type cls)
- {
- // alle Controls aufsammeln
- IEnumerable<Control> controls = control.Controls.Cast<Control>();
- // aus dieser nur die Ziel-Controls zurückgeben
- return controls.SelectMany(ctrl => GetAllClasses(ctrl, cls))
- .Concat(controls)
- .Where(c => c.TestClass(cls));
- }
Als Letztes sammeln wir alle Objekte auf, die ein gemeinsames Interface implementieren.
Der Code ist wie der letzte, nur verwenden wir eine auf Interfaces zugeschnittene Extension:
C#-Quellcode
- /// <summary>
- /// Auflisten aller das Interface Interface1 implementierenden Controls auf der Form
- /// </summary>
- private void button3_Click(object sender, EventArgs e)
- {
- IEnumerable<Control> c = GetAllInterfaces(this, typeof(Interface1));
- // was damit tun:
- MessageBox.Show("Total Interfaces: " + c.Count());
- foreach (Interface1 ctrl in c) // VB2019 macht dies automatisch
- {
- if (ctrl != null) { ctrl.SetTextEx(); }
- }
- }
- /// <summary>
- /// alle Objekte aufsammeln, die das Interface interf implementieren
- /// </summary>
- /// <param name="control">das Parent-Control</param>
- /// <param name="interf">das Ziel-Interface</param>
- private static IEnumerable<Control> GetAllInterfaces(Control control, Type interf)
- {
- // alle Controls aufsammeln
- IEnumerable<Control> controls = control.Controls.Cast<Control>();
- // aus dieser nur die Ziel-Controls zurückgeben
- return controls.SelectMany(ctrl => GetAllInterfaces(ctrl, interf))
- .Concat(controls)
- .Where(c => c.TestInterface(interf));
- }
Als Abschluss noch die Extensions:
C#-Quellcode
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace WindowsFormsApp2
- {
- /// <summary>
- /// Klasse mit Extension-Methoden
- /// </summary>
- static class MyExtensions
- {
- /// <summary>
- /// Überladung zum Testen, ob this Object
- /// von der Klasse cls abgeleitet ist
- /// </summary>
- /// <param name="ob">das Object</param>
- /// <param name="cls">die Klasse</param>
- /// <returns></returns>
- public static bool TestClass(this object ob, Type cls)
- {
- // Basisklassen abfragen
- return ob.GetType().IsSubclassOf(cls);
- }
- /// <summary>
- /// Überladung zum Testen, ob this Object
- /// das Interface interf implementiert
- /// </summary>
- /// <param name="ob">das Object</param>
- /// <param name="interf">das Interface</param>
- /// <returns></returns>
- public static bool TestInterface(this object ob, Type interf)
- {
- // Interfaces abfragen
- Type obType = ob.GetType();
- List<Type> inter = obType.GetInterfaces().ToList();
- return inter.Contains(interf);
- }
- }
- }
Beim Testen hat mich das Studio 2019 überrascht, dass dort eine Reihe von Casts automatisiert werden.
Im Teil mit den Interfaces habe ich das übernommen, bei den Basisklassen nicht, dort kam dieser Vorschlag:
Und für alle, die den Code nicht kopieren wollen, die komplette Solution:
WindowsFormsApp2.zip
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!
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!