Ошибка FlowLayoutPanel Height при использовании AutoSize

У меня есть форма, содержащая TableLayout с 1 столбцом и 3 строками, которая содержит 2 FlowLayoutPanels и текстовое поле. Для всех строк задан автоматический размер, а для столбца установлено значение «Процент = 100%».

Каждый FlowLayoutPanel содержит несколько текстовых полей. FlowLayoutPanels установлены: LeftToRight, AutoSize = true, GrowAndShrink, Docking = Fill.

Схема такова:

Form
    TableLayout (Dock=Fill)
        FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink)
           More controls
        FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink)
           More controls
        TextBox(Dock=Fill, MultiLine=true)

Проблема в том, что если я помещаю FlowLayoutPanel внутри GroupBox, для которого также установлено значение AutoSize = true, высота FlowLayoutPanel установлена ​​неправильно, и он показывает текстовые поля в одной строке, вырезая некоторые текстовые поля из формы.

Схема такова:

Form
    TableLayout (Dock=Fill)
        GroupBox (Dock=Fill, AutoSize=True, GrowShrink) 
            FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink)
               More controls
        GroupBox (Dock=Fill, AutoSize=True, GrowShrink) 
            FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink)
               More controls
        TextBox(Dock=Fill, MultiLine=true)

Кстати, то же самое происходит, если я использую вместо GroupBox, Panel или даже UserControl для хранения FlowLayoutPanel.

Кстати 2, это происходит даже без TableLayout. Я попытался разместить GroupBox (с FlowLayoutPanel) в форме AutoSized, и у меня такое же поведение.

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

Что можно сделать, чтобы исправить эту ошибку?

Пожалуйста, помогите Спасибо, Йорам


p.s: я должен использовать GroupBox, чтобы вокруг текстовых полей был красивый фрейм.


person Yoram    schedule 04.10.2011    source источник


Ответы (3)


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

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

поэтому в приведенном выше примере окончательный макет будет:

Form
    TableLayout (Dock=Fill)
        GroupBox (Dock=Fill, AutoSize=True, GrowShrink) 
            FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink)
                Panel(Dock=Fill, Height = 1, MinimumSize = new System.Drawing.Size( Form.ClientSize.Width - TableLayout.Padding.Horizontal, 1))
                More controls
        GroupBox (Dock=Fill, AutoSize=True, GrowShrink) 
            FlowLayoutPanel(Dock=Fill, AutoSize=True, GrowShrink)
                Panel(Dock=Fill, Height = 1, MinimumSize = new System.Drawing.Size( Form.ClientSize.Width - TableLayout.Padding.Horizontal, 1))
                More controls
        TextBox(Dock=Fill, MultiLine=true)

Надеюсь это поможет.

person Lockszmith    schedule 13.06.2012

Пристыковывая FlowLayoutPanel к GroupBox (или другим контейнерам), вы также можете оставить их AutoSize=false. Я не уверен, но это может сделать групповой ящик «ведущим» элементом управления, когда дело доходит до размера.


Изменить (после вашего комментария)

«Ведущий контроль» - это мои слова, пытающиеся выразить, что размер группового ящика будет определять размер FLP, это не какой-то официальный термин. Проблема в том, что стыковка и автоматическое изменение размеров борьба друг с другом по своей природе, и кто-то должен взять на себя контроль. Это можно сделать только при сокращении стыковки и автоматического изменения размера и путем самостоятельного программирования событий изменения размера.

Немного поигравшись, я наконец придумал эту модель:

Form
    TableLayout (Dock=Fill)
        GroupBox () 
            FlowLayoutPanel(Dock=Fill)
               More controls

И событие изменения размера:

private void Form1_Resize(object sender, EventArgs e)
{
    this.SuspendLayout();
    this.groupBox.Width = this.Width - 20;
    this.groupBox.Height = 
        this.flowLayoutPanel.GetPreferredSize(this.groupBox.Size).Height + 20;
    this.ResumeLayout();
}

Надеюсь, я хорошо вас понял. По крайней мере, это может указать вам правильное направление.

person Gert Arnold    schedule 04.10.2011
comment
Я не могу использовать AutoSize = false для FlowLayuotPanel, потому что, когда форма растягивается пользователем, GroupBox растягивается, а FlowLayoutPanel растягивается вместе с ним, и он может удерживать все элементы управления в одной строке, я хочу, чтобы AutoSize равнялся одному line, уменьшая таким образом высоту GroupBox. - person Yoram; 09.10.2011
comment
Кстати: можете ли вы разместить здесь ссылку, которая объясняет, что вы думаете о ведущем контроле в отношении размеров? Это может привести к решению проблемы, потому что я понятия не имел о «ведущих» элементах управления. Спасибо - person Yoram; 09.10.2011
comment
Я очень ценю твои ответы. Мне придется вернуться к этому через пару дней, потому что я перешел на другое задание. Я отправлю ответ, когда смогу проверить ваше решение. Спасибо!! - person Yoram; 10.10.2011
comment
Привет, ГертАрнольд. Ты сделал это! Ваше решение работает. Единственное изменение, которое мне пришлось добавить, - это запуск события Form1_Resize при запуске приложения, чтобы оно изменяло все размеры в соответствии с этим кодом. Еще раз спасибо!! - person Yoram; 11.10.2011
comment
Пожалуйста. Он научил меня некоторым новым вещам об окнах, изменяющих размер змеиной ямы. - person Gert Arnold; 11.10.2011

Приносим извинения за опоздание на вечеринку, но я хотел бы предложить вам простое вычисление FlowLayoutPanels и его родительского роста, чем использование Ответ Герта Арнольда, поскольку его способ заставляет GetPreferredSize() возвращать Height, равный" одной строке "при удалении дочернего Control - даже если две строки все равно останутся быть обязательным (по крайней мере, в моем случае).

public YodaUserControl
{
  InitializeComponent();
  InitialHeight = parentOfFlp.Height;
}

private int InitialHeight { get; }

private void OnAdded(object sender, ControlEventArgs args)
  => RefreshHeight();

private void OnRemoved(object sender, ControlEventArgs args)
  => RefreshHeight();

private void OnSizeChanged(object sender, EventArgs args)
  => RefreshHeight();

private void RefreshHeight()
{
  if (flpYoda.Controls.Count > 1
      && flpYoda.Controls[0] is Control control)
  {
    parentOfFlpYoda.Height = flpYoda.Height =
      InitialHeight * (int)Math.Ceiling(
        flpYoda.Controls.Count / Math.Floor(
          flpYoda.ClientSize.Width / (double)control.Width));
  }
}

Примечания:

  • Конечно, вы должны заменить YodaUserControl, parentOfFlpYoda и flpYoda своими соответствующими именами.
  • OnAdded, OnRemoved & OnSizeChanged необходимо прикрепить к flpYodas соответствующим событиям ControlAdded, ControlRemoved & SizeChanged.

Если вам нужна дополнительная помощь, просто дайте мне знать в комментарии.

person Yoda    schedule 08.10.2019