[c#] Winforms TableLayoutPanel 프로그래밍 방식으로 행 추가

나는 이것으로 한동안 싸우고 있었고 많은 다른 사람들이 TableLayoutPanel (.net 2.0 Winforms)에도 어려움을 겪고 있음을 발견했습니다.

문제

10 개의 열이 정의 된 ‘빈’tablelayoutpanel을 가져온 다음 런타임에 프로그래밍 방식으로 컨트롤 행 (즉, 셀당 하나의 컨트롤)을 추가하려고합니다.

다음과 같이 간단해야한다고 생각했을 수도 있습니다.

myTableLayoutPanel.Controls.Add(myControl, 0 /* Column Index */, 0 /* Row index */);

그러나 그것은 (나에게) 행을 추가하지 않습니다. 그래서 아마도 행 스타일에 추가

myTableLayoutPanel.RowStyles.Clear();
myTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F));

그러나 그것도 작동하지 않습니다. 나는 주위를 파헤 쳤고 myTableLayoutPanel.RowCount사용이 디자인 타임에서 런타임으로 변경 된다는 것을 알았 으므로 myTableLayoutPanel.RowCount++;RowStyle 항목을 추가하기 전 / 후에도 실제로 다른 행을 추가하지 않습니다!

내가 만나는 또 다른 관련 문제는 컨트롤이 디스플레이에 추가되지만 모두 TableLayoutPanel의 0,0 지점에서 렌더링되며 추가로 셀 경계 내에 있도록 제한되지 않는다는 것입니다. 내부에 표시됩니다 (예 : Dock = DockStyle.Fill 너무 크거나 작게 표시됨).

누군가 런타임에 행 및 컨트롤을 추가하는 작업 예제가 있습니까?



답변

나는 지난주에 이것을했다. 설정 GrowStyle상의를 TableLayoutPanelAddRows또는 AddColumns, 당신의 코드가 작동합니다 :

// Adds "myControl" to the first column of each row
myTableLayoutPanel.Controls.Add(myControl1, 0 /* Column Index */, 0 /* Row index */);
myTableLayoutPanel.Controls.Add(myControl2, 0 /* Column Index */, 1 /* Row index */);
myTableLayoutPanel.Controls.Add(myControl3, 0 /* Column Index */, 2 /* Row index */);

다음은 수행중인 작업과 유사한 작업 코드입니다.

    private Int32 tlpRowCount = 0;

    private void BindAddress()
    {
        Addlabel(Addresses.Street);
        if (!String.IsNullOrEmpty(Addresses.Street2))
        {
            Addlabel(Addresses.Street2);
        }
        Addlabel(Addresses.CityStateZip);
        if (!String.IsNullOrEmpty(Account.Country))
        {
            Addlabel(Address.Country);
        }
        Addlabel(String.Empty); // Notice the empty label...
    }

    private void Addlabel(String text)
    {
        label = new Label();
        label.Dock = DockStyle.Fill;
        label.Text = text;
        label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
        tlpAddress.Controls.Add(label, 1, tlpRowCount);
        tlpRowCount++;
    }

TableLayoutPanel항상 나를 크기에 맞는 수 있습니다. 위의 예에서는 주소 입력란이 2 인 계정 또는 국가에 따라 늘어나거나 줄어들 수있는 주소 카드를 제출하고 있습니다. 테이블 레이아웃 패널의 마지막 행 또는 열이 늘어나 기 때문에 빈 레이블을 거기에 던져서 새 빈 행을 강제하면 모든 것이 잘 정렬됩니다.

다음은 내가 시작하는 테이블을 볼 수 있도록 디자이너 코드입니다.

        //
        // tlpAddress
        // 
        this.tlpAddress.AutoSize = true;
        this.tlpAddress.BackColor = System.Drawing.Color.Transparent;
        this.tlpAddress.ColumnCount = 2;
        this.tlpAddress.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25F));
        this.tlpAddress.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
        this.tlpAddress.Controls.Add(this.pictureBox1, 0, 0);
        this.tlpAddress.Dock = System.Windows.Forms.DockStyle.Fill;
        this.tlpAddress.Location = new System.Drawing.Point(0, 0);
        this.tlpAddress.Name = "tlpAddress";
        this.tlpAddress.Padding = new System.Windows.Forms.Padding(3);
        this.tlpAddress.RowCount = 2;
        this.tlpAddress.RowStyles.Add(new System.Windows.Forms.RowStyle());
        this.tlpAddress.RowStyles.Add(new System.Windows.Forms.RowStyle());
        this.tlpAddress.Size = new System.Drawing.Size(220, 95);
        this.tlpAddress.TabIndex = 0;


답변

이상한 디자인이지만 TableLayoutPanel.RowCount속성은 RowStyles컬렉션 수를 반영하지 않으며 ColumnCount속성과 ColumnStyles컬렉션 도 비슷합니다 .

내가 내 코드에서 필요한 것으로 나타났습니다 수동 업데이트로했다 RowCount/ ColumnCount변경 한 후 RowStyles/을 ColumnStyles.

내가 사용한 코드의 예는 다음과 같습니다.

    /// <summary>
    /// Add a new row to our grid.
    /// </summary>
    /// The row should autosize to match whatever is placed within.
    /// <returns>Index of new row.</returns>
    public int AddAutoSizeRow()
    {
        Panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        Panel.RowCount = Panel.RowStyles.Count;
        mCurrentRow = Panel.RowCount - 1;
        return mCurrentRow;
    }

다른 생각들

  • 그리드 DockStyle.Fill 을 컨트롤로 채우는 데 사용한 적이 없습니다 . Anchors컨트롤 의 속성을 설정하여이 작업을 수행했습니다 .

  • 많은 컨트롤을 추가하는 경우 프로세스 를 호출 SuspendLayout하고 ResumeLayout주변에 있는지 확인하십시오 . 그렇지 않으면 각 컨트롤이 추가 된 후 전체 양식이 다시 배치되므로 작업이 느리게 실행됩니다.


답변

2 열 TableLayoutColumn에 새 행을 추가하는 코드는 다음과 같습니다.

private void AddRow(Control label, Control value)
{
    int rowIndex = AddTableRow();
    detailTable.Controls.Add(label, LabelColumnIndex, rowIndex);
    if (value != null)
    {
        detailTable.Controls.Add(value, ValueColumnIndex, rowIndex);
    }
}

private int AddTableRow()
{
    int index = detailTable.RowCount++;
    RowStyle style = new RowStyle(SizeType.AutoSize);
    detailTable.RowStyles.Add(style);
    return index;
}

레이블 컨트롤은 왼쪽 열에 있고 값 컨트롤은 오른쪽 열에 있습니다. 컨트롤은 일반적으로 Label 유형이며 AutoSize 속성이 true로 설정되어 있습니다.

나는 그것이 너무 중요하다고 생각하지 않지만 참고로 다음은 detailTable을 설정하는 디자이너 코드입니다.

this.detailTable.ColumnCount = 2;
this.detailTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.detailTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.detailTable.Dock = System.Windows.Forms.DockStyle.Fill;
this.detailTable.Location = new System.Drawing.Point(0, 0);
this.detailTable.Name = "detailTable";
this.detailTable.RowCount = 1;
this.detailTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.detailTable.Size = new System.Drawing.Size(266, 436);
this.detailTable.TabIndex = 0;

이 모든 것이 잘 작동합니다. Controls 속성을 사용하여 TableLayoutPanel에서 컨트롤을 동적으로 삭제하는 데 문제가있는 것으로 보입니다 (최소한 일부 버전의 프레임 워크에서). 컨트롤을 제거해야하는 경우 전체 TableLayoutPanel을 삭제하고 새 컨트롤을 만드는 것이 좋습니다.


답변

양식에 두 개의 열이있는 테이블 레이아웃 패널을 만들고 이름을 tlpFields.

그런 다음 테이블 레이아웃 패널에 새 컨트롤을 추가하기 만하면됩니다 (이 경우 1 열에 5 개의 레이블을 추가하고 2 열에 5 개의 텍스트 상자를 추가했습니다).

tlpFields.RowStyles.Clear();  //first you must clear rowStyles

for (int ii = 0; ii < 5; ii++)
{
    Label l1= new Label();
    TextBox t1 = new TextBox();

    l1.Text = "field : ";

    tlpFields.Controls.Add(l1, 0, ii);  // add label in column0
    tlpFields.Controls.Add(t1, 1, ii);  // add textbox in column1

    tlpFields.RowStyles.Add(new RowStyle(SizeType.Absolute,30)); // 30 is the rows space
}

마지막으로 코드를 실행합니다.


답변

방금 내 코드를 살펴 보았습니다. 한 응용 프로그램에서 컨트롤을 추가하기 만하고 인덱스를 지정하지 않고 완료되면 행 스타일을 반복하고 크기 유형을 AutoSize로 설정합니다. 따라서 인덱스를 지정하지 않고 추가하는 것만으로도 의도 한대로 행을 추가하는 것처럼 보입니다 (GrowStyle이 AddRows로 설정된 경우).

다른 응용 프로그램에서 컨트롤을 지우고 RowCount 속성을 필요한 값으로 설정합니다. 이것은 RowStyles를 추가하지 않습니다. 그런 다음 컨트롤을 추가하고 이번에는 인덱스를 지정하고 새 RowStyle ( RowStyles.Add(new RowStyle(...))을 추가하면 이 기능도 작동합니다.

따라서이 방법 중 하나를 선택하면 둘 다 작동합니다. 테이블 레이아웃 패널로 인한 골칫거리를 기억합니다.


답변

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim dt As New DataTable
        Dim dc As DataColumn
        dc = New DataColumn("Question", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)

        dc = New DataColumn("Ans1", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("Ans2", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("Ans3", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("Ans4", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)
        dc = New DataColumn("AnsType", System.Type.GetType("System.String"))
        dt.Columns.Add(dc)


        Dim Dr As DataRow
        Dr = dt.NewRow
        Dr("Question") = "What is Your Name"
        Dr("Ans1") = "Ravi"
        Dr("Ans2") = "Mohan"
        Dr("Ans3") = "Sohan"
        Dr("Ans4") = "Gopal"
        Dr("AnsType") = "Multi"
        dt.Rows.Add(Dr)

        Dr = dt.NewRow
        Dr("Question") = "What is your father Name"
        Dr("Ans1") = "Ravi22"
        Dr("Ans2") = "Mohan2"
        Dr("Ans3") = "Sohan2"
        Dr("Ans4") = "Gopal2"
        Dr("AnsType") = "Multi"
        dt.Rows.Add(Dr)
        Panel1.GrowStyle = TableLayoutPanelGrowStyle.AddRows
        Panel1.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single
        Panel1.BackColor = Color.Azure
        Panel1.RowStyles.Insert(0, New RowStyle(SizeType.Absolute, 50))
        Dim i As Integer = 0

        For Each dri As DataRow In dt.Rows



            Dim lab As New Label()
            lab.Text = dri("Question")
            lab.AutoSize = True

            Panel1.Controls.Add(lab, 0, i)


            Dim Ans1 As CheckBox
            Ans1 = New CheckBox()
            Ans1.Text = dri("Ans1")
            Panel1.Controls.Add(Ans1, 1, i)

            Dim Ans2 As RadioButton
            Ans2 = New RadioButton()
            Ans2.Text = dri("Ans2")
            Panel1.Controls.Add(Ans2, 2, i)
            i = i + 1

            'Panel1.Controls.Add(Pan)
        Next


답변

이것은 TableLayoutPanel에 행과 컨트롤을 추가하는 데 완벽하게 작동합니다.

디자인 페이지에 3 개의 열이있는 빈 Tablelayoutpanel 정의

    Dim TableLayoutPanel3 As New TableLayoutPanel()

    TableLayoutPanel3.Name = "TableLayoutPanel3"

    TableLayoutPanel3.Location = New System.Drawing.Point(32, 287)

    TableLayoutPanel3.AutoSize = True

    TableLayoutPanel3.Size = New System.Drawing.Size(620, 20)

    TableLayoutPanel3.ColumnCount = 3

    TableLayoutPanel3.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single

    TableLayoutPanel3.BackColor = System.Drawing.Color.Transparent

    TableLayoutPanel3.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 26.34146!))

    TableLayoutPanel3.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 73.65854!))

    TableLayoutPanel3.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 85.0!))

    Controls.Add(TableLayoutPanel3)

클릭 할 때마다 행을 추가하는 btnAddRow 버튼을 만듭니다.

     Private Sub btnAddRow_Click(sender As System.Object, e As System.EventArgs) Handles btnAddRow.Click

          TableLayoutPanel3.GrowStyle = TableLayoutPanelGrowStyle.AddRows

          TableLayoutPanel3.RowStyles.Add(New RowStyle(SizeType.Absolute, 20))

          TableLayoutPanel3.SuspendLayout()

          TableLayoutPanel3.RowCount += 1

          Dim tb1 As New TextBox()

          Dim tb2 As New TextBox()

          Dim tb3 As New TextBox()

          TableLayoutPanel3.Controls.Add(tb1 , 0, TableLayoutPanel3.RowCount - 1)

          TableLayoutPanel3.Controls.Add(tb2, 1, TableLayoutPanel3.RowCount - 1)

          TableLayoutPanel3.Controls.Add(tb3, 2, TableLayoutPanel3.RowCount - 1)

          TableLayoutPanel3.ResumeLayout()

          tb1.Focus()

 End Sub