Winforms TableLayoutPanel 프로그래밍 방식으로 행 추가


85

나는 이것으로 한동안 싸우고 있었고 많은 다른 사람들이 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 너무 크거나 작게 표시됨).

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


RowStyle를 추가하면 실제로 RowStyles.Count을 증가 ()
에두아르도 에르난데스

답변:


75

나는 지난주에 이것을했다. 설정 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;

2
빈 자리 표시 자 행에 대한 아이디어에 감사드립니다! 내 크기 문제를 해결했습니다.
JNadal

30

이상한 디자인이지만 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
누구에게나 유용하다면, 제 경우에는 tableLayoutPanel1.ColumnStyles.Clear (); 양식이로드 될 때.
John

17

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을 삭제하고 새 컨트롤을 만드는 것이 좋습니다.


이것은 매우 도움이되었습니다. DockStyle.Fill 속성이 필수적이라는 것을 알았습니다. 또한 카운팅으로 실수하는 것은 의외로 쉽습니다! 또한 스타일로 설정된 열 및 행 크기를 확인하십시오. RowStyle이 AutoSize로 설정되었을 때 TextAlign 설정 (Top, Middle 및 Bottom 중에서)의 일부 의도하지 않은 변형으로 인해 테이블이 이상한 방식으로 추가 행을 생성하는 것처럼 보였지만 그렇지 않았습니다. 일단 당신이 그것을 이해하면 일이 꽤 잘 작동하지만 거기에 도달하는 것은 고통 스럽습니다!
Jan Hettich 2011

7

양식에 두 개의 열이있는 테이블 레이아웃 패널을 만들고 이름을 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
}

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


tlpfields에 어떻게 액세스하고 있습니까? 나는 tablelayoutpanel을 만들었고 그 이름은 tabkelayout이지만 이것에 액세스하는 것은 unabla입니다.
Muneem Habib

tabkelayout 특성과 변화에 가서 @MuneemHabib 수정 민간에서 대중에게
RookieCoder에게

4

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

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

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


나는 이것들이 스스로 작동하는지 확인하기 위해 시도 할 것입니다!
Ash

0
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에 관한 것이고,이 게시물은 DataTable에 관한 것입니다. 게시물은 코드 전용입니다. 요점이 무엇인지 설명하는 텍스트가 없습니다. 코드에도 주석이 없습니다. 그래서 -1.
Nick Alexeev

0

이것은 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

0

동적으로 추가 된 행 및 열 스타일이 적용되지 않는 관련 문제 (이 스레드를 찾은 방법)가있었습니다. 일반적으로 SuspendLayout () / ResumeLayout ()을 최적화로 간주하지만이 경우 코드를 래핑하면 행과 열이 올바르게 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.