Как сделать так, чтобы все столбцы в TableLayoutPanel автоматически менялись до одинаковой ширины? - PullRequest
3 голосов
/ 05 мая 2009

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

К сожалению, поведение TableLayoutPanel не дает мне этого результата.
Использование TableLayoutPanel со всеми столбцами, настроенными на использование одинакового процента элемента управления, дает (в наборе из 7 столбцов) 6 столбцов одинаковой ширины и 7-й столбец переменной ширины.
Я понимаю, что это происходит потому, что для 6 из каждых 7 размеров не существует одинакового количества пикселей-столбцов, которые можно разделить вокруг 7 столбцов, а 7-й столбец является переполнением для этого неравенства.

Я предполагаю, что мне нужно что-то вроде восьмого столбца, который принимает переполнение остальных 7 столбцов, позволяя всем 7 «настоящим» столбцам иметь равную ширину, но для 8-го столбца должно быть шириной 0
Пока что я не могу найти параметр, который разрешает такое поведение.

Может кто-нибудь сказать мне, как заставить TableLayoutPanel делать то, что я хочу, или мне придется начать писать много обходного кода?

EDIT:

В ответ на ответ Якодера я добавил некоторый код, демонстрирующий проблему, а другой - неудачную, наивную попытку ее решения с использованием стандартных функций TableLayoutPanel и свойства Dock

Демонстрация проблемы:

Public Class Form1
Inherits System.Windows.Forms.Form
Public Sub New()
    Me.InitializeComponent()
End Sub
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    Try
        If disposing AndAlso components IsNot Nothing Then
            components.Dispose()
        End If
    Finally
        MyBase.Dispose(disposing)
    End Try
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.  
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
    Me.TableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel
    Me.SuspendLayout()
    '
    'TableLayoutPanel1
    '
    Me.TableLayoutPanel1.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
    Me.TableLayoutPanel1.ColumnCount = 7
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill
    Me.TableLayoutPanel1.Location = New System.Drawing.Point(0, 0)
    Me.TableLayoutPanel1.Name = "TableLayoutPanel1"
    Me.TableLayoutPanel1.RowCount = 7
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.Size = New System.Drawing.Size(261, 264)
    Me.TableLayoutPanel1.TabIndex = 0
    '
    'Form1
    '
    Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
    Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
    Me.ClientSize = New System.Drawing.Size(261, 264)
    Me.Controls.Add(Me.TableLayoutPanel1)
    Me.Name = "Form1"
    Me.Text = "Form1"
    Me.ResumeLayout(False)

End Sub
Friend WithEvents TableLayoutPanel1 As System.Windows.Forms.TableLayoutPanel
Private labelList As List(Of Label)
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)
    labelList = New List(Of Label)
    For JJ As Integer = 0 To Me.TableLayoutPanel1.ColumnCount - 1
        For II As Integer = 0 To Me.TableLayoutPanel1.RowCount - 1
            Dim addLabel As New Label
            Me.TableLayoutPanel1.Controls.Add(addLabel, JJ, II)
            addLabel.Dock = DockStyle.Fill
            Me.labelList.Add(addLabel)
        Next
    Next
End Sub
Private Sub TableLayoutPanel1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles TableLayoutPanel1.Resize
    If Me.labelList IsNot Nothing Then
        For Each labelIn As Label In Me.labelList
            labelIn.Text = labelIn.Width.ToString & ", " & labelIn.Height.ToString
        Next
    End If
End Sub
End Class

Наивное решение:

Public Class Form1
Inherits System.Windows.Forms.Form
Public Sub New()
    Me.InitializeComponent()
End Sub
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    Try
        If disposing AndAlso components IsNot Nothing Then
            components.Dispose()
        End If
    Finally
        MyBase.Dispose(disposing)
    End Try
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.  
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
    Me.TableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel
    Me.SuspendLayout()
    '
    'TableLayoutPanel1
    '
    Me.TableLayoutPanel1.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
    Me.TableLayoutPanel1.ColumnCount = 8
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28572!))
    Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 0.0!))
    Me.TableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill
    Me.TableLayoutPanel1.Location = New System.Drawing.Point(0, 0)
    Me.TableLayoutPanel1.Name = "TableLayoutPanel1"
    Me.TableLayoutPanel1.RowCount = 8
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571!))
    Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 0.0!))
    Me.TableLayoutPanel1.Size = New System.Drawing.Size(261, 264)
    Me.TableLayoutPanel1.TabIndex = 0
    '
    'Form1
    '
    Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
    Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
    Me.ClientSize = New System.Drawing.Size(261, 264)
    Me.Controls.Add(Me.TableLayoutPanel1)
    Me.Name = "Form1"
    Me.Text = "Form1"
    Me.ResumeLayout(False)

End Sub
Friend WithEvents TableLayoutPanel1 As System.Windows.Forms.TableLayoutPanel
Private labelList As List(Of Label)
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)
    labelList = New List(Of Label)
    For JJ As Integer = 0 To Me.TableLayoutPanel1.ColumnCount - 1
        For II As Integer = 0 To Me.TableLayoutPanel1.RowCount - 1
            Dim addLabel As New Label
            Me.TableLayoutPanel1.Controls.Add(addLabel, JJ, II)
            addLabel.Dock = DockStyle.Fill
            Me.labelList.Add(addLabel)
        Next
    Next
End Sub
Private Sub TableLayoutPanel1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles TableLayoutPanel1.Resize
    If Me.labelList IsNot Nothing Then
        For Each labelIn As Label In Me.labelList
            labelIn.Text = labelIn.Width.ToString & ", " & labelIn.Height.ToString
        Next
    End If
End Sub
End Class

Приношу свои извинения за ужасную производительность этого кода при перерисовке.

Ответы [ 3 ]

10 голосов
/ 20 мая 2009

Может быть, я не совсем понял вопрос, но ... вот что я сделал:

  1. Создать новую форму
  2. Удалите TableLayoutPanel на форму и установите Dock = Fill
  3. В окне дизайна формы (если вы используете VS) нажмите на маленькую стрелку на TableLayoutPanel, чтобы открыть меню с заданиями и перейти к «Редактировать строки и столбцы ...»
  4. В этом окне добавьте столько столбцов, сколько вам нужно, и установите для всех них значение «Процент» от всего размера и везде ставьте одинаковое число. Вы можете ввести любое число, просто убедитесь, что оно одинаковое, VS автоматически сделает сумму равной 100%.

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

Если вы не в VS или у вас проблемы с этим методом, этот код я автоматически сгенерировал в своем классе Designer:

    this.tableLayoutPanel1.ColumnCount = 7;
    this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571F));
    this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571F));
    this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571F));
    this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571F));
    this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571F));
    this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571F));
    this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 14.28571F));
1 голос
/ 29 мая 2009

Я пытался настроить это в своей среде, а также прочитал ваше сообщение около 6 или 7 раз, и я не могу определить, что именно вы пытаетесь сделать. У меня есть 6 столбцов, которые пристыковали объекты SWF GroupBox, чтобы они были заполнены столбцами с одинаковой шириной%, чтобы я мог легко видеть их изменение размера. У меня также есть 7-й столбец с абсолютной шириной 0px для работы в качестве переполнения. Это работает так, как я ожидал.

Что я не могу определить, так это то, что не так с этой настройкой и / или что вы пытаетесь заставить ее сделать. Не могли бы вы лучше описать, что вам нужно для TableLayoutPanel?

0 голосов
/ 25 марта 2014
public MainForm()
{
    TableLayoutPanel pnlDragAndDrop = new TableLayoutPanel();

    // make the panel full width
    pnlDragAndDrop.Dock = DockStyle.Fill;

    // be sure to add columns and rows explicitly!
    pnlDragAndDrop.ColumnCount = 2;
    pnlDragAndDrop.RowCount = 1;

    // add a border just for testing
    pnlDragAndDrop.CellBorderStyle = 
        TableLayoutPanelCellBorderStyle.InsetDouble;
    pnlDragAndDrop.CellPaint += 
        new TableLayoutCellPaintEventHandler(TblLayoutPanel_CellPaint);

    // add a column style for each column!
    for (int i = 0; i < pnlDragAndDrop.ColumnCount * pnlDragAndDrop.RowCount; ++i)
    {
        pnlDragAndDrop.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
    }

    // add the panel to the form
    this.Controls.Add(pnlDragAndDrop);
}

private void TblLayoutPanel_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
    // Add a border around each cell
    e.Graphics.DrawLine(
        Pens.Black, 
        e.CellBounds.Location, 
        new Point(e.CellBounds.Right, e.CellBounds.Top)
        );
}
...