WPF: ¿Cómo recorro todos los controles en una ventana?

¿Cómo recorro todos los controles en una ventana en WPF?

Clase para obtener una lista de todos los componentes para niños de un control:

class Utility { private static StringBuilder sbListControls; public static StringBuilder GetVisualTreeInfo(Visual element) { if (element == null) { throw new ArgumentNullException(String.Format("Element {0} is null !", element.ToString())); } sbListControls = new StringBuilder(); GetControlsList(element, 0); return sbListControls; } private static void GetControlsList(Visual control, int level) { const int indent = 4; int ChildNumber = VisualTreeHelper.GetChildrenCount(control); for (int i = 0; i < = ChildNumber - 1; i++) { Visual v = (Visual)VisualTreeHelper.GetChild(control, i); sbListControls.Append(new string(' ', level * indent)); sbListControls.Append(v.GetType()); sbListControls.Append(Environment.NewLine); if (VisualTreeHelper.GetChildrenCount(v) > 0) { GetControlsList(v, level + 1); } } } } 

Encontré esto en la documentación de MSDN, así que ayuda.

 // Enumerate all the descendants of the visual object. static public void EnumVisual(Visual myVisual) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++) { // Retrieve child visual at specified index value. Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i); // Do processing of the child visual object. // Enumerate children of the child visual object. EnumVisual(childVisual); } } 

Me parece más simple. Lo usé para encontrar cuadros de texto en un formulario y borrar sus datos.

De esta manera es superior al método MSDN, en el sentido de que es reutilizable, y permite el aborto anticipado del bucle (es decir, vía, break; , etc.) – optimiza el bucle for ya que guarda una llamada al método para cada iteración – – y también le permite usar bucles for para recorrer los hijos de Visual, o incluso recurse sus hijos y sus nietos – por lo que es mucho más fácil de consumir.

Para consumirlo, puede simplemente escribir un ciclo foreach regular (o incluso usar LINQ):

 foreach (var ctrl in myWindow.GetChildren()) { // Process children here! } 

O si no desea recurse:

 foreach (var ctrl in myWindow.GetChildren(false)) { // Process children here! } 

Para que funcione, solo necesita poner este método de extensión en cualquier clase estática, y luego podrá escribir código como el anterior siempre que lo desee:

 public static IEnumerable GetChildren(this Visual parent, bool recurse = true) { if (parent != null) { int count = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < count; i++) { // Retrieve child visual at specified index value. var child = VisualTreeHelper.GetChild(parent, i) as Visual; if (child != null) { yield return child; if (recurse) { foreach (var grandChild in child.GetChildren(true)) { yield return grandChild; } } } } } } 

Además, si no le gusta que la recursividad esté activada de manera predeterminada, puede cambiar la statement del método de extensión para que recurse = false sea ​​el comportamiento predeterminado.

He usado lo siguiente para obtener todos los controles.

  public static IList GetControls(this DependencyObject parent) { var result = new List(); for (int x = 0; x < VisualTreeHelper.GetChildrenCount(parent); x++) { DependencyObject child = VisualTreeHelper.GetChild(parent, x); var instance = child as Control; if (null != instance) result.Add(instance); result.AddRange(child.GetControls()); } return result; } 

Una ligera variación en la respuesta de MSDN … simplemente pase una lista vacía de objetos visuales en ella y su colección se completará con todos los elementos visuales secundarios:

 ///  /// Enumerate all the descendants (children) of a visual object. ///  /// Starting visual (parent). /// Collection, into which is placed all of the descendant visuals. public static void EnumVisual(Visual parent, List collection) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { // Get the child visual at specified index value. Visual childVisual = (Visual)VisualTreeHelper.GetChild(parent, i); // Add the child visual object to the collection. collection.Add(childVisual); // Recursively enumerate children of the child visual object. EnumVisual(childVisual, collection); } }