Подтвердить что ты не робот

WPF: Как я прокручиваю все элементы управления в окне?

Как мне перебирать все элементы управления в окне в WPF?

4b9b3361

Ответ 1

Класс для получения списка всех дочерних компонентов элемента управления:

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

Ответ 2

Я нашел это в MSDN documenation, чтобы он помог.

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

Мне кажется проще. Я использовал его для поиска текстовых полей в форме и очистки их данных.

Ответ 3

Этот способ превосходит метод MSDN, поскольку он многократно используется и позволяет раннее прерывание цикла (т.е. через, break; и т.д.) - он оптимизирует цикл 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<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;
                    }
                }
            }
        }
    }
}

Кроме того, если вы не хотите, чтобы рекурсия была включена по умолчанию, вы можете изменить объявление метода расширения, чтобы recurse = false выполнялось по умолчанию.

Ответ 4

Я использовал следующее, чтобы получить все элементы управления.

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

Ответ 5

Небольшое отклонение ответа MSDN... просто передайте в него пустой список объектов Visual, и ваша коллекция будет заполнена всеми дочерними изображениями:

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