Определите во время выполнения, позволяет ли элемент управления добавлять к нему другие элементы управления во время разработки.

Мне нужно манипулировать всеми элементами управления в форме. Я в порядке с доступом к коллекции Controls, чтобы сделать это. Проблема возникает при попытке включить любые элементы управления, содержащиеся в элементах управления контейнером, таких как GroupBox или Panel. Я мог бы рекурсивно повторять собственную коллекцию Controls каждого элемента управления, но тогда это обращается ко всем составляющим элементам управления для контейнеров, не связанных с проектированием.

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

Как определить, является ли элемент управления контейнером времени разработки, чтобы избежать обработки тех, которые им не являются?

Я пытался проверить атрибут Designer, но это возвращает значение null как для ComboBox, так и для GroupBox:

foreach(Attribute attr in typeof(ctl).GetCustomAttributes(typeof(Attribute), false))
{
    if(typeof(DesignerAttribute).IsAssignableFrom(attr.GetType()))
{
    DesignerAttribute da = (DesignerAttribute)attr;
    }
}

ctl относится к типу Control, а в моем тестировании это либо Combox, либо GroupBox.

В обоих случаях GetCustomAttributes возвращает массив из 1 атрибута, который является значком панели инструментов.

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

Как обнаружить контейнер времени разработки?


person Richard Payne    schedule 11.02.2014    source источник
comment
Какой элемент управления содержит другие элементы управления, которые вам не нужны? Я знаю только один - PropertyGrid и его очень легко исключить из рекурсии.   -  person Sinatr    schedule 11.02.2014
comment
Любой составной пользовательский элемент управления. Я не могу явно проверить все возможности.   -  person Richard Payne    schedule 11.02.2014
comment
только UserControl? Исключить их всех!   -  person Sinatr    schedule 11.02.2014
comment
А как насчет пользовательских элементов управления, которые действуют как контейнеры времени разработки?   -  person Richard Payne    schedule 11.02.2014
comment
Есть ли? Подкласс Panel не является UserControl.   -  person Sinatr    schedule 11.02.2014
comment
Хорошо, хорошо. Таким образом, пользовательский контроль — это просто произвольный термин для обозначения элемента управления, который не является производным от стандартного элемента управления .net?   -  person Richard Payne    schedule 11.02.2014
comment
Очень мрачно. У каждого элемента управления есть коллекция Controls, в которую можно добавлять элементы управления. Например, вполне допустимо добавить кнопку в текстовое поле. Дизайнер обращает внимание на возвращаемое значение Control.GetStyle(). Когда вы перетаскиваете элемент управления на поверхность конструктора, он ищет элемент управления, для которого включен стиль ControlStyles.Container. Это всегда, по крайней мере, заканчивается на Форме. Это защищенный метод, требуется отражение.   -  person Hans Passant    schedule 11.02.2014
comment
Спасибо Ганс. Напишите это в ответе, и я приму это.   -  person Richard Payne    schedule 11.02.2014


Ответы (1)


На случай, если Ганс не вернется и кому-то это интересно, вот мое решение проблемы, основанное на предложении Ганса Пассанта:

    public static bool IsContainerControl(this Control ctl)
    {
        if (ctl == null)
            return false;

        MethodInfo GetStyle = ctl.GetType().GetMethod("GetStyle", BindingFlags.NonPublic | BindingFlags.Instance);
        if (GetStyle == null)
            return false;

        return (bool)GetStyle.Invoke(ctl, new object[] { ControlStyles.ContainerControl });
    }
person Richard Payne    schedule 12.02.2014
comment
Выглядит хорошо для меня. Пожалуйста, закройте свой вопрос, отметив свой пост как ответ. - person Hans Passant; 12.02.2014
comment
Да, я пока не могу. У меня есть какое-то дурацкое ограничение в 48 часов. - person Richard Payne; 12.02.2014
comment
Причина, по которой я попросил вас опубликовать ответ, который я бы принял, заключается в том, что, насколько я понимаю, этот сайт оценивает своих пользователей по качеству их ответов. Вы определенно должны получить признание за то, что указали мне правильное направление. - person Richard Payne; 12.02.2014
comment
Мне уже поставили оценки, мне кажется, вам это пригодится гораздо больше, чем мне :) - person Hans Passant; 12.02.2014
comment
ЛОЛ, так что у вас есть. Не показывает репутацию в комментариях. Это большие числа. :) - person Richard Payne; 12.02.2014
comment
Ганс, не могли бы вы взглянуть на мой дополнительный вопрос. Увидеть ниже. - person Richard Payne; 13.02.2014
comment
Так нельзя, это не форум. Вам нужно нажать кнопку «Задать вопрос» еще раз. - person Hans Passant; 13.02.2014