Как получить от всех детей родительский контроль?

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

Я понятия не имею, как это сделать.

foreach (Control control in Controls)
{
  if (control.HasChildren)
  {
    ??
  }
}

5 ответов

Решение

Если вы хотите только непосредственных детей, используйте

...
var children = control.Controls.OfType<Control>();
...

Если вам нужны все элементы управления из иерархии (т. Е. Все элементы дерева под определенным элементом управления), используйте:

    private IEnumerable<Control> GetControlHierarchy(Control root)
    {
        var queue = new Queue<Control>();

        queue.Enqueue(root);

        do
        {
            var control = queue.Dequeue();

            yield return control;

            foreach (var child in control.Controls.OfType<Control>())
                queue.Enqueue(child);

        } while (queue.Count > 0);

    }

Затем вы можете использовать что-то вроде этого в форме:

    private void button1_Click(object sender, EventArgs e)
    {
        /// get all of the controls in the form's hierarchy in a List<>
        var controlList = GetControlHierarchy(this).ToList();

        foreach (var control in controlList)
        {
            /// do something with this control
        }
    }

Обратите внимание, что .ToList() немедленно оценит весь Enumerable, что исключает любую полезную выгоду, которую вы можете получить от реализации сопрограммы.

Элементы управления имеют MyControl.Controls Коллекция, которую вы можете сделать foreach на.

Каждый элемент управления также имеет Parent свойство, которое дает вам родительский контроль.

Вы можете написать рекурсивный метод, если вам нужно пройти неизвестное количество уровней.

Может быть, это может быть полезно для кого-то:

public void GetControlsCollection(Control root,ref List<Control> AllControls,  Func<Control,Control> filter)
{
    foreach (Control child in root.Controls)
    {
        var childFiltered = filter(child);
        if (childFiltered != null) AllControls.Add(child);
        if (child.HasControls()) GetControlsCollection(child, ref AllControls, filter);
    }
}

Это рекурсивная функция для получения коллекции элементов управления с возможностью применения фильтра (для примера по типу). И пример:

 List<Control> resultControlList = new List<Control>();
 GetControlsCollection(rootControl, ref resultControlList, new Func<Control,Control>(ctr => (ctr is DropDownList)? ctr:null ));

Он вернет все DropDownLists в rootControl и всех его детей

Вероятно, слишком сложный, но используя Linq и некоторые идеи сверху / в других местах:

    public static IEnumerable<Control> GetAllChildren(this Control root) {
        var q = new Queue<Control>(root.Controls.Cast<Control>());

        while (q.Any()) {
            var next = q.Dequeue();
            next.Controls.Cast<Control>().ToList().ForEach(q.Enqueue);

            yield return next;
        }
    }

Вот краткая рекурсивная функция расширения с использованием Linq:

              /// <summary>
        /// Recursive function to get all descendant controls.
        /// </summary>
        public static IEnumerable<Control> GetDescendants(this Control control)
        {
            var children = control.Controls.OfType<Control>();
            return children.Concat(children.SelectMany(c => GetDescendants(c)));
        }
Другие вопросы по тегам