Как получить ВСЕ дочерние элементы управления формы Windows Forms определенного типа (кнопка / текстовое поле)? - PullRequest
107 голосов
/ 06 августа 2010

Мне нужно получить все элементы управления в форме типа x. Я почти уверен, что когда-то видел этот код, который использовал что-то вроде этого:

dim ctrls() as Control
ctrls = Me.Controls(GetType(TextBox))

Я знаю, что могу перебрать все элементы управления, получая детей с помощью рекурсивной функции, но Есть ли что-то более простое или более простое, например, следующее?

Dim Ctrls = From ctrl In Me.Controls Where ctrl.GetType Is Textbox

Ответы [ 23 ]

1 голос
/ 02 июля 2017

Вот мой метод расширения.Это очень эффективно и лениво.

Использование:

var checkBoxes = tableLayoutPanel1.FindChildControlsOfType<CheckBox>();

foreach (var checkBox in checkBoxes)
{
    checkBox.Checked = false;
}

Код:

public static IEnumerable<TControl> FindChildControlsOfType<TControl>(this Control control) where TControl : Control
    {
        foreach (var childControl in control.Controls.Cast<Control>())
        {
            if (childControl.GetType() == typeof(TControl))
            {
                yield return (TControl)childControl;
            }
            else
            {
                foreach (var next in FindChildControlsOfType<TControl>(childControl))
                {
                    yield return next;
                }
            }
        }
    }
1 голос
/ 08 марта 2017

Чистое и простое решение (C #):

static class Utilities {
    public static List<T> GetAllControls<T>(this Control container) where T : Control {
        List<T> controls = new List<T>();
        if (container.Controls.Count > 0) {
            controls.AddRange(container.Controls.OfType<T>());
            foreach (Control c in container.Controls) {
                controls.AddRange(c.GetAllControls<T>());
            }
        }

        return controls;
    }
}

Получить все текстовые поля:

List<TextBox> textboxes = myControl.GetAllControls<TextBox>();
1 голос
/ 05 декабря 2016
   IEnumerable<Control> Ctrls = from Control ctrl in Me.Controls where ctrl is TextBox | ctrl is GroupBox select ctr;

Лямбда-выражения

IEnumerable<Control> Ctrls = Me.Controls.Cast<Control>().Where(c => c is Button | c is GroupBox);
1 голос
/ 09 мая 2015
public List<Control> GetAllChildControls(Control Root, Type FilterType = null)
{
    List<Control> AllChilds = new List<Control>();
    foreach (Control ctl in Root.Controls) {
        if (FilterType != null) {
            if (ctl.GetType == FilterType) {
                AllChilds.Add(ctl);
            }
        } else {
            AllChilds.Add(ctl);
        }
        if (ctl.HasChildren) {
            GetAllChildControls(ctl, FilterType);
        }
    }
    return AllChilds;
}
1 голос
/ 08 октября 2013

Вот решение.

https://stackoverflow.com/a/19224936/1147352

Я написал этот фрагмент кода и выбрал только панели, вы можете добавить дополнительные переключатели или ifs.в нем

0 голосов
/ 29 декабря 2017

Для тех, кто ищет VB-версию кода C # Адама, написанного как расширение класса Control:

''' <summary>Collects child controls of the specified type or base type within the passed control.</summary>
''' <typeparam name="T">The type of child controls to include. Restricted to objects of type Control.</typeparam>
''' <param name="Parent">Required. The parent form control.</param>
''' <returns>An object of type IEnumerable(Of T) containing the control collection.</returns>
''' <remarks>This method recursively calls itself passing child controls as the parent control.</remarks>
<Extension()>
Public Function [GetControls](Of T As Control)(
    ByVal Parent As Control) As IEnumerable(Of T)

    Dim oControls As IEnumerable(Of Control) = Parent.Controls.Cast(Of Control)()
    Return oControls.SelectMany(Function(c) GetControls(Of T)(c)).Concat(oControls.Where(Function(c) c.GetType() Is GetType(T) Or c.GetType().BaseType Is GetType(T))
End Function

ПРИМЕЧАНИЕ. Я добавил BaseType соответствия для любых производных пользовательских элементов управления.Вы можете удалить это или даже сделать его необязательным параметром, если хотите.

Использование

Dim oButtons As IEnumerable(Of Button) = Me.GetControls(Of Button)()
0 голосов
/ 01 февраля 2017
    public IEnumerable<T> GetAll<T>(Control control) where T : Control
    {
        var type = typeof(T);
        var controls = control.Controls.Cast<Control>().ToArray();
        foreach (var c in controls.SelectMany(GetAll<T>).Concat(controls))
            if (c.GetType() == type) yield return (T)c;
    }
0 голосов
/ 11 октября 2016
    public static IEnumerable<T> GetAllControls<T>(this Control control) where T : Control
    {
        foreach (Control c in control.Controls)
        {
            if (c is T)
                yield return (T)c;
            foreach (T c1 in c.GetAllControls<T>())
                yield return c1;
        }
    }
0 голосов
/ 29 декабря 2015

Хотя несколько других пользователей опубликовали адекватные решения, я хотел бы опубликовать более общий подход, который может быть более полезным.

Это в значительной степени основано на ответе Джелтона.

public static IEnumerable<Control> AllControls(
    this Control control, 
    Func<Control, Boolean> filter = null) 
{
    if (control == null)
        throw new ArgumentNullException("control");
    if (filter == null)
        filter = (c => true);

    var list = new List<Control>();

    foreach (Control c in control.Controls) {
        list.AddRange(AllControls(c, filter));
        if (filter(c))
            list.Add(c);
    }
    return list;
}
0 голосов
/ 13 августа 2015

Вы можете попробовать это, если хотите:)

    private void ClearControls(Control.ControlCollection c)
    {
        foreach (Control control in c)
        {
            if (control.HasChildren)
            {
                ClearControls(control.Controls);
            }
            else
            {
                if (control is TextBox)
                {
                    TextBox txt = (TextBox)control;
                    txt.Clear();
                }
                if (control is ComboBox)
                {
                    ComboBox cmb = (ComboBox)control;
                    if (cmb.Items.Count > 0)
                        cmb.SelectedIndex = -1;
                }

                if (control is CheckBox)
                {
                    CheckBox chk = (CheckBox)control;
                    chk.Checked = false;
                }

                if (control is RadioButton)
                {
                    RadioButton rdo = (RadioButton)control;
                    rdo.Checked = false;
                }

                if (control is ListBox)
                {
                    ListBox listBox = (ListBox)control;
                    listBox.ClearSelected();
                }
            }
        }
    }
    private void btnClear_Click(object sender, EventArgs e)
    {
        ClearControls((ControlCollection)this.Controls);
    }
...