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

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

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

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

Dim Ctrls = From ctrl In Me.Controls Where ctrl.GetType Is Textbox
113
задан Vadim Ovchinnikov 5 March 2018 в 12:59
поделиться

4 ответа

Вот вам еще один вариант. Я протестировал его, создав образец приложения, а затем поместил GroupBox и GroupBox в исходный GroupBox. Внутри вложенного GroupBox я поместил 3 элемента управления TextBox и кнопку. Это код, который я использовал (даже включает рекурсию, которую вы искали)

public IEnumerable<Control> GetAll(Control control,Type type)
{
    var controls = control.Controls.Cast<Control>();

    return controls.SelectMany(ctrl => GetAll(ctrl,type))
                              .Concat(controls)
                              .Where(c => c.GetType() == type);
}

Чтобы протестировать его в событии загрузки формы, мне нужно было подсчитать количество всех элементов управления внутри исходного GroupBox

private void Form1_Load(object sender, EventArgs e)
{
    var c = GetAll(this,typeof(TextBox));
    MessageBox.Show("Total Controls: " + c.Count());
}

И он каждый раз возвращал правильный счет, так что я думаю, что это сработает идеально для того, что вы ищете :)

216
ответ дан 24 November 2019 в 02:39
поделиться

Это может сработать:

Public Function getControls(Of T)() As List(Of T)
    Dim st As New Stack(Of Control)
    Dim ctl As Control
    Dim li As New List(Of T)

    st.Push(Me)

    While st.Count > 0
        ctl = st.Pop
        For Each c In ctl.Controls
            st.Push(CType(c, Control))
            If c.GetType Is GetType(T) Then
                li.Add(CType(c, T))
            End If
        Next
    End While

    Return li
End Function

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

0
ответ дан 24 November 2019 в 02:39
поделиться

В C # (поскольку вы пометили его как таковой) вы можете использовать выражение LINQ, подобное этому:

List<Control> c = Controls.OfType<TextBox>().Cast<Control>().ToList();

Редактировать для рекурсии:

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

List<Control> ControlList = new List<Control>();
private void GetAllControls(Control container)
{
    foreach (Control c in container.Controls)
    {
        GetAllControls(c);
        if (c is TextBox) ControlList.Add(c);
    }
}

Это можно сделать в одном операторе LINQ с помощью функции Descendants , хотя я с ней не так хорошо знаком. См. на этой странице для получения дополнительной информации.

Отредактируйте 2, чтобы вернуть коллекцию:

Как предложил @ProfK, метод, который просто возвращает желаемые элементы управления, вероятно, является лучшей практикой. Чтобы проиллюстрировать это, я изменил код следующим образом:

private IEnumerable<Control> GetAllTextBoxControls(Control container)
{
    List<Control> controlList = new List<Control>();
    foreach (Control c in container.Controls)
    {
        controlList.AddRange(GetAllTextBoxControls(c));
        if (c is TextBox)
            controlList.Add(c);
    }
    return controlList;
}
31
ответ дан 24 November 2019 в 02:39
поделиться

Для этого можно использовать запрос LINQ. Это будет запрашивать все в форме типа TextBox

var c = from controls in this.Controls.OfType<TextBox>()
              select controls;
7
ответ дан 24 November 2019 в 02:39
поделиться