WPF: How do I loop through the all controls in a window?

前端 未结 5 906
无人及你
无人及你 2020-11-27 05:52

How do I loop through the all controls in a window in WPF?

相关标签:
5条回答
  • 2020-11-27 06:28

    I've used the following to get all controls.

        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;
        }
    
    0 讨论(0)
  • 2020-11-27 06:37

    Class to get a list of all the children's components of a 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);
                    }
                }
            }
        } 
    
    0 讨论(0)
  • 2020-11-27 06:38

    I found this in the MSDN documenation so it helps.

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

    Looks simpler to me. I used it to find textboxes in a form and clear their data.

    0 讨论(0)
  • 2020-11-27 06:38

    A slight variation on the MSDN answer ... just pass in an empty List of Visual objects into it and your collection will be populated with all the child visuals:

    /// <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);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 06:42

    This way is superior to the MSDN method, in that it's reusable, and it allows early aborting of the loop (i.e. via, break;, etc.) -- it optimizes the for loop in that it saves a method call for each iteration -- and it also lets you use regular for loops to loop through a Visual's children, or even recurse it's children and it's grand children -- so it's much simpler to consume.

    To consume it, you can just write a regular foreach loop (or even use LINQ):

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

    Or if you don't want to recurse:

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

    To make it work, you just need put this extension method into any static class, and then you'll be able to write code like the above anytime you like:

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

    Also, if you don't like recursion being on by default, you can change the extension method's declaration to have recurse = false be the default behavior.

    0 讨论(0)
提交回复
热议问题