Элементы управления Dynami c TableLayoutPanel поддерживают ширину границы - PullRequest
1 голос
/ 09 марта 2020

По умолчанию у меня есть TableLayoutPanel с 1 столбцом и тремя строками. Верхняя и нижняя строки имеют дочерние TableLayoutPanels, которые содержат кнопки, а средняя строка имеет TextBox. Кнопки в верхнем и нижнем рядах динамически отображаются при загрузке на основе значений в My.Settings, и по умолчанию имеется пять кнопок (и, следовательно, пять столбцов).

Способ, которым я динамически устанавливаю кнопки Текст, а также, если они должны быть удалены, таков (повторяется еще четыре раза):

Dim visibleButtonCount As Integer = {My.Settings.ValueVisible1, My.Settings.ValueVisible2, My.Settings.ValueVisible3, My.Settings.ValueVisible4, My.Settings.ValueVisible5}.Where(Function(setting) setting).Count()
Dim buttonWidth As Double = 100 / visibleButtonCount

ButtonValueDown1.Text = $"- {My.Settings.Value1.ToString("N3")}"
ButtonValueUp1.Text = $"+ {My.Settings.Value1.ToString("N3")}"
If (Not My.Settings.ValueVisible1) Then
    ButtonValueDown1.Parent.Controls.Remove(ButtonValueDown1)
    ButtonValueUp1.Parent.Controls.Remove(ButtonValueUp1)

    With TableLayoutPanelDown.ColumnStyles.Item(0)
        .SizeType = SizeType.Absolute
        .Width = 0
    End With
    With TableLayoutPanelUp.ColumnStyles.Item(0)
        .SizeType = SizeType.Absolute
        .Width = 0
    End With
Else
    TableLayoutPanelDown.ColumnStyles.Item(0).Width = buttonWidth
    TableLayoutPanelUp.ColumnStyles.Item(0).Width = buttonWidth
End If

Проблема, с которой я сталкиваюсь, заключается в том, что, когда все 5 кнопок видны, правая большинство кнопок в верхнем и нижнем рядах - это грипп sh с TextBox в среднем ряду , но всякий раз, когда одна или несколько кнопок удаляются, самые правые кнопки больше не являются гриппом sh (см. образ). all buttons visible one or more buttons removed

Что может быть причиной этого? Стоит отметить, что все элементы управления имеют отступ / отступ 0. 0. 1016 *

1 Ответ

1 голос
/ 10 марта 2020

Чтобы позволить TableLayoutPanel динамически изменять размер своих столбцов во время выполнения, когда элементы управления неопределенного размера добавляются в коллекцию TableLayoutPanel.Controls, одним эффективным методом является установка во время разработки столбцов . TableLayoutStyle.SizeType до SizeType.Percent .
При добавлении столбцов с помощью дизайнера мы можем установить значение Percent каждого нового столбца равным 100%. TableLayoutPanel автоматически определит правильное процентное значение, основываясь на его текущем размере и количестве добавленных столбцов.

В текущем сценарии у нас есть внешняя TableLayoutPanel с одним столбцом, в котором размещены другие TableLayoutPanels в некоторых из ее ячеек.
→ Внутренние TableLayoutPanels установлены на Dock = Fill, заполняя ячейку, которую они занимают.
→ Внутренние TLP будут содержать переменное количество элементов управления, поэтому им необходимо динамически корректировать размер дочерних элементов управления, чтобы заполнить ширину внешнего контейнера TLP.

Пример макета во время разработки:

TableLayoutPanel AutoSize DesignTime

Верхняя, светло-серая, 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

В примере кода кнопки «Добавить» и «Удалить» называются 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...