WPF - Getting a collection of all controls for a g

2019-05-18 15:30发布

问题:

I'm trying to get a list of all controls of a given type on a given Page, but I'm encountering problems. It seems that it's possible that the VisualTreeHelper only returns controls that have been loaded? I tried turning off Virtualization, but that didn't seem to help. Can anyone think of another way to get all the control or perhaps force a load of the UI so that the following method does work?

I borrowed this from MSDN:

 public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
        {
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

                    if (child != null && child is T)
                    {
                        yield return (T)child;
                    }

                    foreach (T childOfChild in FindVisualChildren<T>(child))
                    {
                        yield return childOfChild;
                    }
                }
            }
        }

回答1:

See the following thread: Finding all controls of a given type across a TabControl

The answer from Tao Liang is a good explanation

The reason is that the WPF designer want to optimize the performance of TabControl. Suppose there are 5 TabItems, and each TabItem contains alot of children. If WPF program have to construct and render all the children, it will be very slow. But if TabControl only handle the children just in the current selected TabItem, much memory will be saved.

You can give the logical tree a try instead.
Here is an example implementation of this, see if it works better for you

Use it like this..

List<Button> buttons = GetLogicalChildCollection<Button>(yourPage);

GetLogicalChildCollection

public static List<T> GetLogicalChildCollection<T>(object parent) where T : DependencyObject
{
    List<T> logicalCollection = new List<T>();
    GetLogicalChildCollection(parent as DependencyObject, logicalCollection);
    return logicalCollection;
}
private static void GetLogicalChildCollection<T>(DependencyObject parent, List<T> logicalCollection) where T : DependencyObject
{
    IEnumerable children = LogicalTreeHelper.GetChildren(parent);
    foreach (object child in children)
    {
        if (child is DependencyObject)
        {
            DependencyObject depChild = child as DependencyObject;
            if (child is T)
            {
                logicalCollection.Add(child as T);
            }
            GetLogicalChildCollection(depChild, logicalCollection);
        }
    }
}