【问题标题】:Dynamic TableLayoutPanel Controls Keep Border Width动态 TableLayoutPanel 控件保持边框宽度
【发布时间】:2020-03-09 03:48:59
【问题描述】:

默认情况下,我有一个 1 列和 3 行的 TableLayoutPanel。顶行和底行有包含按钮的子 TableLayoutPanel,而中间行有一个 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 个按钮都可见时,顶行和底行中最右边的按钮与中间行中的 TextBox 齐平但是只要有一个或更多按钮被删除最右边的按钮不再齐平(见图)。

这可能是什么原因造成的?值得一提的是,所有控件的边距/内边距均为 0。

【问题讨论】:

  • TableLayoutPanelUp.ColumnStyles(0).SizeType = SizeType.AutoSize TableLayoutPanelUp.Refresh()
  • 我的意思是,假设TableLayoutPanelUp.Dock = Fill
  • @Jimi 谢谢你,我今晚一回家就试试这个。我担心按钮的宽度不会全部相同(例如,一个会比其他按钮长得多),这就是我尝试设置百分比的原因。
  • 这就是.SizeType = SizeType.AutoSize 的原因。 TLP 自动设置百分比。
  • @Jimi - 每当我实施您的建议时,按钮的宽度都相同,但它们都小于填充剩余空间所需的宽度。不确定它是否值得一提,但 TableLayoutPanel 和按钮已停靠​​以填充并且 TableLayoutPanel AutoSize 为 true。

标签: .net vb.net winforms tablelayoutpanel


【解决方案1】:

为了允许 TableLayoutPanel 在运行时动态调整其列的大小,当将未定义大小的控件添加到 TableLayoutPanel.Controls 集合时,一种有效的方法是在设计时设置列的 TableLayoutStyle.SizeTypeSizeType.Percent.
使用设计器添加Columns时,我们可以将每个新Column的Percent值设置为100%。 TableLayoutPanel 将根据其当前大小和添加的列数自动确定正确的百分比值。

在当前场景中,我们有一个外部 TableLayoutPanel,其中一个 Column 在它的某些 Cell 中托管其他 TableLayoutPanel。
→ 内部 TableLayoutPanel 设置为Dock = Fill,填充它们占用的 Cell。
→ 内部 TLP 将承载可变数量的 Control,因此它们需要动态调整子 Control 的大小以填充外部 TLP 容器的宽度。

设计时的示例布局:

上面浅灰色的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 已停靠,这将迫使它评估新值并生成新布局,重新计算所有值以适应停靠要求。

结果的视觉样本:

在示例代码中,添加和删除按钮命名为btnAddControlbtnRemoveControl,组合框命名为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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 2013-09-13
    • 1970-01-01
    • 2015-06-02
    • 2018-09-04
    • 2020-10-28
    相关资源
    最近更新 更多