Winforms TableLayoutPanel thêm các hàng theo lập trình


85

Tôi đã đấu tranh với điều này trong một thời gian và nhận thấy rằng một số người khác cũng đấu tranh với TableLayoutPanel (.net 2.0 Winforms).

Vấn đề

Tôi đang cố gắng lấy một bảng điều khiển tablelayout 'trống', có 10 cột được xác định, sau đó trong thời gian chạy thêm các hàng điều khiển theo cách lập trình (tức là một điều khiển cho mỗi ô).

Người ta có thể nghĩ rằng nó phải đơn giản như

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

Nhưng điều đó (đối với tôi) không thêm các hàng. Vì vậy, có thể thêm theo kiểu hàng

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

Nhưng điều đó cũng không hiệu quả. Tôi đã tìm hiểu kỹ và phát hiện ra rằng việc myTableLayoutPanel.RowCountsử dụng thay đổi từ thời gian thiết kế sang thời gian chạy, do đó việc làm myTableLayoutPanel.RowCount++;này không thực sự thêm một hàng khác, thậm chí không phải trước / sau khi thêm mục nhập RowStyle cho nó!

Một vấn đề liên quan khác mà tôi đang gặp phải là các điều khiển sẽ được thêm vào màn hình, nhưng tất cả chúng chỉ đơn giản được hiển thị tại điểm 0,0 của TableLayoutPanel, ngoài ra chúng thậm chí không bị ràng buộc trong giới hạn Ô mà chúng được cho là hiển thị bên trong (tức là với Dock = DockStyle.Fill, chúng vẫn xuất hiện quá lớn / quá nhỏ).

Ai đó có ví dụ làm việc về việc thêm hàng & điều khiển trong thời gian chạy không?


Thêm một RowStyle thực sự sẽ làm tăng RowStyles.Count ()
Eduardo Hernández

Câu trả lời:


75

Tôi vừa mới làm điều này tuần trước. Đặt GrowStyletrên TableLayoutPanelđể AddRowshoặc AddColumns, sau đó mã của bạn nên làm việc:

// 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 */);

Đây là một số mã làm việc có vẻ giống với những gì bạn đang làm:

    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++;
    }

Các TableLayoutPanelluôn mang lại cho tôi phù hợp với kích thước. Trong ví dụ của tôi ở trên, tôi đang gửi một thẻ địa chỉ có thể phát triển hoặc thu nhỏ tùy thuộc vào tài khoản có dòng địa chỉ thứ hai hoặc quốc gia. Bởi vì hàng hoặc cột cuối cùng của bảng bố cục bảng sẽ kéo dài, tôi ném nhãn trống vào đó để buộc một hàng trống mới, sau đó mọi thứ sẽ xếp hàng đẹp mắt.

Đây là mã thiết kế để bạn có thể xem bảng tôi bắt đầu với:

        //
        // 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
Ví dụ hoàn hảo, đơn giản.
RandomInsano

2
Cảm ơn vì ý tưởng cho một hàng giữ chỗ trống! Đã giải quyết các vấn đề về kích thước của tôi.
JNadal

30

Đó là một thiết kế kỳ lạ, nhưng thuộc TableLayoutPanel.RowCounttính không phản ánh số lượng của RowStylesbộ sưu tập và tương tự đối với ColumnCounttài sản và ColumnStylesbộ sưu tập.

Những gì tôi thấy tôi cần trong mã của mình là cập nhật thủ công RowCount/ ColumnCountsau khi thực hiện các thay đổi đối với RowStyles/ ColumnStyles.

Đây là một ví dụ về mã tôi đã sử dụng:

    /// <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;
    }

Suy nghĩ khác

  • Tôi chưa bao giờ sử dụng DockStyle.Fillđể thực hiện điều khiển điền vào một ô trong Grid; Tôi đã thực hiện điều này bằng cách thiết lập thuộc Anchorstính của điều khiển.

  • Nếu bạn đang thêm nhiều điều khiển, hãy đảm bảo rằng bạn gọi SuspendLayoutResumeLayoutxung quanh quy trình, những thứ khác sẽ chạy chậm vì toàn bộ biểu mẫu được tải lại sau khi mỗi điều khiển được thêm vào.


2
Nếu nó hữu ích cho bất kỳ ai, trong trường hợp của tôi, tôi phải gọi tableLayoutPanel1.ColumnStyles.Clear (); khi biểu mẫu đang tải.
John

17

Đây là mã của tôi để thêm hàng mới vào TableLayoutColumn hai cột:

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;
}

Điều khiển nhãn nằm ở cột bên trái và điều khiển giá trị ở cột bên phải. Các điều khiển thường thuộc loại Nhãn và có thuộc tính Tự động kích thước của chúng được đặt thành true.

Tôi không nghĩ nó quá quan trọng, nhưng để tham khảo, đây là mã thiết kế để thiết lập 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;

Tất cả điều này hoạt động tốt. Bạn nên biết rằng có vẻ như có một số vấn đề với việc loại bỏ các điều khiển từ TableLayoutPanel bằng cách sử dụng động thuộc tính Controls (ít nhất là trong một số phiên bản của khung). Nếu bạn cần xóa các điều khiển, tôi khuyên bạn nên hủy toàn bộ TableLayoutPanel và tạo một bảng điều khiển mới.


Điều này rất hữu ích. Tôi thấy rằng thuộc tính DockStyle.Fill là cần thiết. Ngoài ra, rất dễ mắc lỗi khi đếm! Ngoài ra, hãy lưu ý kích thước cột và hàng được đặt với các kiểu. Tôi nhận thấy rằng khi RowStyle được đặt thành AutoSize, một số biến thể không chủ ý trong cài đặt TextAlign (trong số Trên cùng, Giữa và Dưới cùng) khiến bảng có vẻ như đang tạo thêm các hàng theo một cách kỳ lạ nào đó, nhưng không phải vậy. Mọi thứ hoạt động khá tốt khi bạn đã tìm ra, nhưng thật khó khăn khi đến đó!
Jan Hettich

7

Tạo bảng bố cục bảng có hai cột trong biểu mẫu của bạn và đặt tên cho nó tlpFields.

Sau đó, chỉ cần thêm điều khiển mới vào bảng bố trí bảng (trong trường hợp này, tôi đã thêm 5 nhãn trong hộp văn bản cột-1 và 5 trong cột-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
}

Cuối cùng, chạy mã.


làm thế nào bạn đang truy cập tlpfields? Tôi đã tạo tablelayoutpanel và tên của nó là tabkelayout nhưng tôi không có quyền truy cập vào cái này.
Muneem Habib

@MuneemHabib đi đến tài sản tabkelayout và thay đổi Modifiers từ riêng tư thành công
RookieCoder

4

Tôi chỉ nhìn vào mã của tôi. Trong một ứng dụng, tôi chỉ thêm các điều khiển, nhưng không chỉ định chỉ mục và khi hoàn tất, tôi chỉ cần lặp qua các kiểu hàng và đặt kiểu kích thước thành Tự động kích thước. Vì vậy, chỉ thêm chúng mà không chỉ định các chỉ số dường như sẽ thêm các hàng như dự định (với điều kiện GrowStyle được đặt thành AddRows).

Trong một ứng dụng khác, tôi xóa các điều khiển và đặt thuộc tính RowCount thành giá trị cần thiết. Điều này không thêm RowStyles. Sau đó, tôi thêm các điều khiển của mình, lần này chỉ định các chỉ số và thêm một RowStyle ( RowStyles.Add(new RowStyle(...)) mới và điều này cũng hoạt động.

Vì vậy, hãy chọn một trong những phương pháp này, cả hai đều hoạt động. Tôi nhớ những điều đau đầu mà bảng bố trí bảng đã gây ra cho tôi.


Tôi sẽ thử những cái này để xem nó có tự hoạt động không!
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

Câu hỏi là về TableLayoutPanel, bài này là về DataTable. Bài đăng chỉ mang tính chất mã. Nó không có bất kỳ văn bản nào mô tả điểm có thể là gì. Không có bình luận nào trong mã. Vì vậy, -1.
Nick Alexeev

0

Điều này hoạt động hoàn hảo để thêm hàng và điều khiển trong TableLayoutPanel.

Xác định một Tablelayoutpanel trống với 3 cột trong trang thiết kế

    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)

Tạo một nút btnAddRow để thêm hàng trên mỗi lần nhấp

     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

Tôi vừa gặp sự cố liên quan (đó là cách tôi tìm thấy chuỗi này), trong đó kiểu hàng và cột được thêm động của tôi không có hiệu lực. Tôi thường coi SuspendLayout () / ResumeLayout () là tối ưu hóa, nhưng trong trường hợp này, việc bọc mã của tôi trong chúng đã làm cho các hàng và cột hoạt động chính xác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.