Чтобы позволить TableLayoutPanel динамически изменять размер своих столбцов во время выполнения, когда элементы управления неопределенного размера добавляются в коллекцию TableLayoutPanel.Controls
, одним эффективным методом является установка во время разработки столбцов . TableLayoutStyle.SizeType до SizeType.Percent .
При добавлении столбцов с помощью дизайнера мы можем установить значение Percent
каждого нового столбца равным 100%
. TableLayoutPanel автоматически определит правильное процентное значение, основываясь на его текущем размере и количестве добавленных столбцов.
В текущем сценарии у нас есть внешняя TableLayoutPanel с одним столбцом, в котором размещены другие TableLayoutPanels в некоторых из ее ячеек.
→ Внутренние TableLayoutPanels установлены на Dock = Fill
, заполняя ячейку, которую они занимают.
→ Внутренние TLP будут содержать переменное количество элементов управления, поэтому им необходимо динамически корректировать размер дочерних элементов управления, чтобы заполнить ширину внешнего контейнера TLP.
Пример макета во время разработки:
![TableLayoutPanel AutoSize DesignTime](https://i.stack.imgur.com/4dMTO.gif)
Верхняя, светло-серая, TableLayoutPanel представляет tableLayoutPanelUp
элемент управления в примере кода.
Поскольку дочерние элементы управления (здесь кнопки) добавляются и / или удаляются во время выполнения, внутренняя таблица TableLayoutPanel должна равномерно изменять их размер, чтобы заполните внешний размер контейнера TableLayoutPanel, чтобы сохранить макет.
► TableLayoutPanel может выполнить этот макет должным образом, при условии, что мы указываем столбец и строку (ячейку), которые будут содержать элемент управления при добавлении его в коллекцию Controls
.
Если мы не будем т. TableLayoutPanel не может правильно определить новый размер своих дочерних элементов управления, когда ему необходимо изменить их размер, чтобы заполнить доступное пространство.
В примере кода дочерние кнопки добавляются в коллекцию List(Of Button)
(для удобства), затем кнопки добавляются в TableLayoutPanel (с именем tableLayoutPanelUp
, как в вопросе).
■ Дочерние элементы управления добавляются в раздел SuspendLayout () / PerformLayout () , чтобы приостановить макет до тех пор, пока не будут добавлены все элементы управления, а затем выполнить макет, когда все штук на месте.
■ для каждого нового элемента управления его ячейка задается явно с использованием методов TableLayoutPanel SetRow () и SetColumn () .
■ Чтобы удалить элемент управления, экземпляр элемента управления указывается с использованием метода Controls.Remove(Control)
(элемент управления не утилизируется, поэтому он все еще внутри его контейнера. Список ) и соответствующий столбец ColumnStyles.Width
(представляющий значение Percent
) установлен на 0
.
■ Когда добавляется дочерний элемент управления, снова вызываются SetRow()
и SetColumn()
, чтобы определить ячейку, которая будет содержать новый элемент управления. В этом случае размер (процент) соответствующего столбца устанавливается на 100 / tableLayoutPanelUp.ColumnCount
. Поскольку TableLayoutPanel пристыкован, это заставит его оценить новые значения и сгенерировать новый макет, пересчитав все значения в соответствии с требованиями стыковки.
Визуальный пример результата:
![TableLayoutPanel AutoSize Runtime](https://i.stack.imgur.com/SlnXX.gif)
В примере кода кнопки «Добавить» и «Удалить» называются btnAddControl
и btnRemoveControl
, ComboBox назван cboControlsIndexes
Private tlpButtons As List(Of Button) = Nothing
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
tlpButtons = New List(Of Button)() From {
New Button() With {.Dock = DockStyle.Fill, .FlatStyle = FlatStyle.Flat, .Text = "Button1"},
New Button() With {.Dock = DockStyle.Fill, .FlatStyle = FlatStyle.Flat, .Text = "Button2"},
New Button() With {.Dock = DockStyle.Fill, .FlatStyle = FlatStyle.Flat, .Text = "Button3"},
New Button() With {.Dock = DockStyle.Fill, .FlatStyle = FlatStyle.Flat, .Text = "Button4"},
New Button() With {.Dock = DockStyle.Fill, .FlatStyle = FlatStyle.Flat, .Text = "Button5"}
}
cboControlsIndexes.DisplayMember = "Text"
cboControlsIndexes.DataSource = tlpButtons
tableLayoutPanelUp.SuspendLayout()
For i As Integer = 0 To tlpButtons.Count - 1
tableLayoutPanelUp.Controls.Add(tlpButtons(i))
tableLayoutPanelUp.SetRow(tlpButtons(i), 0)
tableLayoutPanelUp.SetColumn(tlpButtons(i), i)
Next
tableLayoutPanelUp.ResumeLayout(True)
tableLayoutPanelUp.PerformLayout()
End Sub
Private Sub btnRemoveControl_Click(sender As Object, e As EventArgs) Handles btnRemoveControl.Click
Dim removeAtIndex As Integer = cboControlsIndexes.SelectedIndex
tableLayoutPanelUp.Controls.Remove(tlpButtons(removeAtIndex))
tableLayoutPanelUp.ColumnStyles(removeAtIndex).Width = 0
End Sub
Private Sub btnAddControl_Click(sender As Object, e As EventArgs) Handles btnAddControl.Click
Dim addAtIndex As Integer = cboControlsIndexes.SelectedIndex
tableLayoutPanelUp.Controls.Add(tlpButtons(addAtIndex))
tableLayoutPanelUp.SetRow(tlpButtons(addAtIndex), 0)
tableLayoutPanelUp.SetColumn(tlpButtons(addAtIndex), addAtIndex)
tableLayoutPanelUp.ColumnStyles(addAtIndex).Width = 100 / tableLayoutPanelUp.ColumnCount
End Sub