foreach Цикл управления пропускает скрытые элементы управления

Программа, над которой я сейчас работаю, использует C# WinForms (на 2.0 .NET Framework, хотя в данном случае это, вероятно, не будет иметь значения). Дизайн требует возможности масштабирования формы и всех ее элементов управления вверх и вниз. Я сделал это, перебирая каждый из элементов управления, сохраняя их исходные размеры и расположение и получая их отношение к исходному размеру формы для масштабирования. Это выглядит примерно так:

const int SCALE_W = 600;
const int SCALE_H = 500;

...

if (!listsBuilt){
    foreach (Control c in this.Controls){
        sizes.Add(c.Size);
        positions.Add(c.Location);
    }
    listsBuilt = true;
}

int count = 0;
foreach (Control c in this.Controls){
    c.Height = this.Height * (sizes[count].Height / SCALE_H);
    c.Width = this.Width * (sizes[count].Width / SCALE_W);
    c.Left = this.Width * (positions[count].X / SCALE_W);
    c.Top = this.Height * (positions[count].Y / SCALE_H);
}

До сих пор он отлично работал, и я смог сделать его глобальным и применить ко всем своим формам. Проблема возникает, когда в форме есть скрытые объекты. Я предполагал, что они все еще будут созданы, и когда программа впервые зациклится, чтобы получить исходный размер / положение объектов, она подберет их, но это не так. Если я переключаю режимы в форме и показываю некоторые объекты, которых раньше не было, а затем изменяю их размер, объекты оказываются в неправильных местах с неправильными размерами.

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

foreach (Control c in this.Controls){
    c.Show();
    c.Hide();
}

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

Изменить: видимость скрытых элементов управления установлена ​​​​на «False» через конструктор. Они отображаются с помощью функции .Show() на более позднем этапе программы.

Edit Again!: Получается, что проблема даже не в видимости. Проблема скорее в том, что как только отображается элемент управления, он, кажется, перетасовывает свой индекс в коллекции элементов управления, поэтому, когда я возвращаюсь и сравниваю их, они не в том порядке, в котором они были, когда я впервые заполнил сравнение Список. Это означает, что один элемент управления, скорее всего, будет сравниваться со значениями другого и в конечном итоге будет иметь эту позицию и размер, а не свои собственные.


person KChaloux    schedule 21.07.2010    source источник
comment
Может быть, я не понимаю вашего вопроса, но как насчет использования свойств Anchor и Dock вместо написания кода?   -  person s.m.    schedule 21.07.2010
comment
Вы добавляете эти скрытые элементы управления к этому?   -  person Luiscencio    schedule 21.07.2010
comment
@sm Anchor и док работают только для изменения положения кода. Мне нужно, чтобы элементы управления также изменяли размер (что они и делают в рабочей версии, которая у меня есть сейчас).   -  person KChaloux    schedule 21.07.2010
comment
они делают? У меня были элементы управления, закрепленные на двух противоположных сторонах, и их размер изменился, как и ожидалось.   -  person Kawa    schedule 21.07.2010
comment
@Kawa: Если вы привяжете их к противоположным сторонам, они могут масштабироваться, но по моему опыту (я сделал это в начале и решил, что мне не нравится результат), это не всегда работает хорошо. Особенно, когда вы используете нестандартные элементы управления, такие как я, у которых есть куча разных частей, которые не так хорошо масштабируются вместе.   -  person KChaloux    schedule 21.07.2010


Ответы (2)


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

person dlras2    schedule 21.07.2010
comment
Будет ли TableLayoutPanel также изменять размер элементов управления, а также перемещать их? - person KChaloux; 21.07.2010
comment
Да — закрепите TableLayoutPanel в своей основной форме, а затем создайте столько строк/столбцов, сколько вам нужно. Элементы управления могут охватывать несколько строк/столбцов с соответствующими Span свойствами. Затем привяжите элементы управления к сторонам их ячейки, к которой вы хотите изменить их размер. Например, чтобы иметь 4 кнопки, каждая из которых занимает четверть экрана, сделайте 2x2 TableLayoutPanel, поместите по одной кнопке в каждую и привяжите каждую кнопку ко всем четырем сторонам. - person dlras2; 21.07.2010
comment
Кроме того, убедитесь, что все ваши строки и столбцы установлены в процентах, а не в абсолютных размерах. (В диалоговом окне «Редактировать строки/столбцы».) См. msdn .microsoft.com/en-us/library/ для получения дополнительных сведений и примеров. Это отличный инструмент макета. - person dlras2; 21.07.2010

Если я вас правильно понимаю, вам будет гораздо лучше привязка ваших элементов управления. Они будут масштабироваться вверх и вниз, чтобы поддерживать расстояние от краев содержащего их элемента управления, и все это будет обрабатываться для вас самим WinForms.

person Martin Harris    schedule 21.07.2010
comment
Я не думаю, что привязка — это то, чего хочет ОП; привязка поддерживает абсолютное расстояние между краем элемента управления и его родителем, тогда как они ищут относительное расстояние. - person dlras2; 21.07.2010
comment
@ Дэниел Расмуссен: Точно. Как у меня сейчас, элементы управления увеличиваются и уменьшаются в размере вместе с формой и сохраняют то же относительное расстояние и отношение к самой форме и друг к другу. На самом деле я довольно рано пытался использовать Anchor/Dock для некоторого масштабирования, но это просто не очень хорошо работает с некоторыми нестандартными элементами управления National Instrument, которые я использую. - person KChaloux; 21.07.2010
comment
@KChaloux Только что попытался сам воспроизвести вашу проблему, и я получаю данные при загрузке формы для всех элементов управления, независимо от того, видны они, скрыты или невидимы. Можете ли вы обновить свой вопрос, чтобы показать, как вы скрываете элементы управления? Они все еще в коллекции элементов управления, верно? - person Martin Harris; 21.07.2010
comment
Я думаю, что это на самом деле основная часть проблемы. Их нет в коллекции элементов управления до тех пор, пока где-то в коде они явно не получат .Show()n. где-то в коде. Они начинаются со свойством Visible false в конструкторе. - person KChaloux; 21.07.2010
comment
@KChaloux В тестовом приложении, которое я только что написал (путем перетаскивания элементов управления из панели инструментов на форму и использования инспектора свойств для установки видимости), сгенерированный дизайнером код поместил элементы управления в коллекцию, и ваш цикл правильно вытащил все правильные размеры и места. Если ваши элементы управления не находятся в коллекции их родителей, я предполагаю, что вы каким-то образом контролируете добавление? - person Martin Harris; 21.07.2010
comment
Это странно... Мне нужно проверить дизайнера и посмотреть, правильно ли они добавляются в коллекцию. Бьюсь об заклад, это моя проблема. - person KChaloux; 21.07.2010