c# - tutorial - wpf progress bar
WPF: ¿Cómo hago un bucle a través de todos los controles en una ventana? (5)
Clase para obtener una lista de todos los componentes de un control para niños:
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);
}
}
}
}
¿Cómo hago un bucle a través de todos los controles en una ventana en WPF?
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.
Esta forma es superior al método MSDN, es reutilizable y permite el aborto temprano del bucle (es decir, a través de, break;
etc.) optimiza el bucle for en que guarda una llamada de método para cada iteración. - y también te permite usar los bucles regulares para recorrer los hijos de un Visual, o incluso recibir a sus hijos y sus nietos, por lo que es mucho más sencillo de consumir.
Para consumirlo, simplemente puede escribir un bucle foreach regular (o incluso usar LINQ):
foreach (var ctrl in myWindow.GetChildren())
{
// Process children here!
}
O si no quieres repetirte:
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 cuando lo desee:
public static IEnumerable<Visual> 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 te gusta que la recursión esté activada de forma predeterminada, puedes cambiar la declaración 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<Control> GetControls(this DependencyObject parent)
{
var result = new List<Control>();
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 pequeña variación en la respuesta de MSDN ... simplemente pase una Lista de objetos visuales vacía y su colección se rellenará con todos los elementos visuales secundarios:
/// <summary>
/// Enumerate all the descendants (children) of a visual object.
/// </summary>
/// <param name="parent">Starting visual (parent).</param>
/// <param name="collection">Collection, into which is placed all of the descendant visuals.</param>
public static void EnumVisual(Visual parent, List<Visual> 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);
}
}