Найти компоненты в форме окна С# (не управляет)
Я знаю, как найти и собрать список всех элементов управления, используемых в Windows Form.
Что-то вроде этого:
static public void FillControls(Control control, List<Control> AllControls)
{
String controlName = "";
controlName = control.Name;
foreach (Control c in control.Controls)
{
controlName = c.Name;
if ((control.Controls.Count > 0))
{
AllControls.Add(c);
FillControls(c, AllControls);
}
}
}
Однако эта функция не извлекает невизуальные компоненты в нижней части формы, такие как HelpProvider, ImageList, TableAdapters, DataSets и т.д.
Есть ли способ получить список этих компонентов?
Edit:
Спасибо @HighCore за то, что указали, что я использую System.ComponentModel.Component вместо этого в подобной функции, я получаю список с такими компонентами, как ImageList, Справочный провайдер и BindingSource.
Тем не менее, я все еще пропускаю из этого списка TableAdapters и DataSets. Я полагаю, потому что те наследуют непосредственно от Object.
Пожалуйста. Не относитесь ко мне к более старым сообщениям, которые показывают аналогичную функцию для моего, и это только получает список элементов управления.
Изменить: Почему отрицательные голоса? На этот вопрос никогда не отвечали!
Ответы
Ответ 1
Удивительно, но единственный способ сделать это - через отражение.
private IEnumerable<Component> EnumerateComponents()
{
return from field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where typeof (Component).IsAssignableFrom(field.FieldType)
let component = (Component) field.GetValue(this)
where component != null
select component;
}
Ответ 2
Все элементы управления, созданные через конструктор, должны иметь закрытое поле, называемое "компоненты" типа IContainer. Вы можете использовать отражение, чтобы получить значение этого поля, если оно существует, а затем выполнить итерацию по компонентам.
Этот метод отличается от другого ответа тем, что он будет возвращать только компоненты, добавленные в форму с использованием конструктора, в отличие от всех полей, которые могут быть преобразованы как Компонент.
public IEnumerable<Component> GetComponents(Control c)
{
FieldInfo fi = c.GetType()
.GetField("components", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (fi?.GetValue(c) is IContainer container)
{
return container.Components.OfType<Component>();
}
else
{
return Enumerable.Empty<Component>();
}
}