WPF:如何循环窗口中的所有控件?

如何在WPF窗口中循环所有控件?

用于获取控件的所有子组件的列表的类:

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); } } } } 

我在MSDN文档中发现了这一点,所以它有所帮助。

 // 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); } } 

看起来对我来说更简单。 我用它来查找表单中的文本框并清除它们的数据。

这种方式优于MSDN方法,因为它是可重用的,并且它允许循环的早期中止(即通过, break;等) – 它优化了for循环,因为它为每次迭代保存了一个方法调用 – – 它还允许你使用常规for循环来循环Visual的孩子,甚至可以递归它的孩子和它的大孩子 – 所以它更容易消费。

要使用它,你可以编写一个常规的foreach循环(甚至使用LINQ):

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

或者如果你不想递归:

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

为了使它工作,你只需要将这个扩展方法放入任何静态类中,然后你就可以随时编写如上所述的代码:

 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; } } } } } } 

此外,如果您不喜欢默认情况下启用递归,则可以更改扩展方法的声明以使recurse = false成为默认行为。

我已经使用以下内容来获取所有控件。

  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; } 

MSDN答案略有不同……只需将一个空的Visual对象列表传入其中,您的集合将填充所有子视觉效果:

 ///  /// 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); } }