Winforms TableLayoutPanel เพิ่มแถวโดยทางโปรแกรม


85

ฉันต่อสู้กับสิ่งนี้มาระยะหนึ่งแล้วและพบว่ามีคนอีกจำนวนมากที่ต่อสู้กับ TableLayoutPanel (.net 2.0 Winforms) เช่นกัน

ปัญหา

ฉันกำลังพยายามใช้ tablelayoutpanel 'ว่าง' ซึ่งมีการกำหนด 10 คอลัมน์จากนั้นในรันไทม์เพิ่มแถวของตัวควบคุมโดยใช้โปรแกรม (เช่นหนึ่งตัวควบคุมต่อเซลล์)

อาจมีคนคิดว่ามันควรจะเรียบง่ายเหมือน

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 สำหรับมัน!

ปัญหาที่เกี่ยวข้องอีกประการหนึ่งที่ฉันพบคือการควบคุมจะถูกเพิ่มลงในจอแสดงผล แต่พวกเขาทั้งหมดจะแสดงผลที่จุด 0,0 ของ TableLayoutPanel นอกจากนี้ยังไม่ได้ถูก จำกัด ให้อยู่ในขอบเขตของเซลล์ที่ควรจะเป็น แสดงอยู่ภายใน (เช่นกับ Dock = DockStyle หากยังคงมีขนาดใหญ่เกินไป / เล็กเกินไป)

ใครมีตัวอย่างการทำงานของการเพิ่มแถวและการควบคุมที่รันไทม์?


การเพิ่ม RowStyle จะช่วยเพิ่ม RowStyles.Count ()
Eduardo Hernández

คำตอบ:


75

ฉันเพิ่งทำเมื่อสัปดาห์ที่แล้ว การตั้งค่าGrowStyleในTableLayoutPanelการAddRowsหรือ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เสมอให้ฉันเหมาะกับขนาด ในตัวอย่างของฉันด้านบนฉันกำลังยื่นบัตรที่อยู่ที่อาจขยายหรือลดขนาดขึ้นอยู่กับบัญชีที่มีที่อยู่บรรทัดที่สองหรือประเทศ เนื่องจากแถวหรือคอลัมน์สุดท้ายของแผงเค้าโครงตารางจะยืดออกฉันจึงโยนป้ายกำกับที่ว่างเข้าไปเพื่อบังคับแถวว่างใหม่จากนั้นทุกอย่างก็เรียงลำดับอย่างสวยงาม

นี่คือรหัสนักออกแบบเพื่อให้คุณสามารถดูตารางที่ฉันเริ่มต้นด้วย:

        //
        // 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หลังจากการเปลี่ยนแปลง/RowStylesColumnStyles

นี่คือตัวอย่างรหัสที่ฉันเคยใช้:

    /// <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 (); เมื่อแบบฟอร์มกำลังโหลด
จอห์น

17

นี่คือรหัสของฉันสำหรับการเพิ่มแถวใหม่ใน 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;

ทั้งหมดนี้ใช้งานได้ดี คุณควรทราบว่าดูเหมือนจะมีปัญหาในการกำจัดการควบคุมจาก TableLayoutPanel แบบไดนามิกโดยใช้คุณสมบัติ Controls (อย่างน้อยในบางเวอร์ชันของเฟรมเวิร์ก) หากคุณต้องการลบการควบคุมฉันขอแนะนำให้ทิ้ง TableLayoutPanel ทั้งหมดและสร้างใหม่


สิ่งนี้มีประโยชน์มาก ฉันพบว่าแอตทริบิวต์ DockStyle.Fill มีความสำคัญ นอกจากนี้ยังง่ายมากที่จะทำผิดพลาดกับการนับ! นอกจากนี้โปรดสังเกตขนาดคอลัมน์และแถวที่กำหนดด้วยสไตล์ ฉันพบว่าเมื่อ RowStyle ถูกตั้งค่าเป็น AutoSize รูปแบบที่ไม่ได้ตั้งใจบางอย่างในการตั้งค่า TextAlign (จากด้านบนกลางและด้านล่าง) ทำให้ดูเหมือนว่าตารางกำลังสร้างแถวเพิ่มเติมด้วยวิธีแปลก ๆ แต่ก็ไม่เป็นเช่นนั้น สิ่งนี้ใช้ได้ผลดีเมื่อคุณคิดออก แต่การไปที่นั่นก็เจ็บปวด!
Jan Hettich

7

tlpFieldsสร้างแผงรูปแบบตารางที่มีคอลัมน์ที่สองในรูปแบบของคุณและชื่อมัน

จากนั้นเพิ่มการควบคุมใหม่ลงในแผงเค้าโครงตาราง (ในกรณีนี้ฉันเพิ่ม 5 ป้ายกำกับในคอลัมน์ -1 และ 5 กล่องข้อความในคอลัมน์ -2)

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 แต่ฉันไม่กล้าที่จะเข้าถึงสิ่งนี้
Muneem Habib

@MuneemHabib ไปที่คุณสมบัติ tabkelayout และเปลี่ยนModifiersจากส่วนตัวเป็นสาธารณะ
RookieCoder

4

ฉันเพิ่งดูรหัสของฉัน ในแอปพลิเคชั่นเดียวฉันเพิ่มตัวควบคุม แต่ไม่ได้ระบุดัชนีและเมื่อเสร็จแล้วฉันก็วนซ้ำสไตล์แถวและตั้งค่าประเภทขนาดเป็นขนาดอัตโนมัติ ดังนั้นเพียงแค่เพิ่มโดยไม่ระบุดัชนีดูเหมือนว่าจะเพิ่มแถวตามที่ตั้งใจไว้ (หาก GrowStyle ถูกตั้งค่าเป็น AddRows)

ในแอปพลิเคชันอื่นฉันล้างตัวควบคุมและตั้งค่าคุณสมบัติ RowCount เป็นค่าที่ต้องการ สิ่งนี้ไม่ได้เพิ่ม RowStyles จากนั้นฉันเพิ่มการควบคุมคราวนี้ระบุดัชนีและเพิ่ม RowStyle ( RowStyles.Add(new RowStyle(...)) ใหม่และสิ่งนี้ก็ใช้ได้

ดังนั้นเลือกหนึ่งในวิธีการเหล่านี้ทั้งสองได้ผล ฉันจำได้ว่าแผงผังตารางทำให้ฉันปวดหัว


ฉันจะให้พวกนี้ลองดูว่ามันทำงานเองหรือเปล่า!
เถ้า

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

กำหนด Tablelayoutpanel ว่างที่มี 3 คอลัมน์ในหน้าออกแบบ

    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.