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

Ton*_*ony 18 .net c# wpf

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

Jul*_*len 16

我在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Bra*_*s83 11

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

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

foreach (var ctrl in myWindow.GetChildren())
{
    // Process children here!
}
Run Code Online (Sandbox Code Playgroud)

或者如果你不想递归:

foreach (var ctrl in myWindow.GetChildren(false))
{
    // Process children here!
}
Run Code Online (Sandbox Code Playgroud)

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

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;
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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


abm*_*bmv 7

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

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);
                }
            }
        }
    } 
Run Code Online (Sandbox Code Playgroud)

  • 不是通过逻辑树循环比循环通过可视树更好,更有效. (2认同)