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 ()
Едуардо Ернандес

Відповіді:


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
Ідеальний, простий приклад.
RandomInsano

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робив, щоб елемент управління заповнював клітинку в Grid; Я зробив це, встановивши 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 (серед верхнього, середнього та нижнього) показали, що таблиця генерує зайві рядки якимось дивним чином, але це не так. Справа працює досить добре, як тільки ви це зрозумієте, але потрапляти туди було боляче!
Ян Хеттіч,

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, але я не маю доступу до цього.
Мунім Хабіб

@MuneemHabib перейти до властивостей вкладки та змінити Модифікатори з приватних на загальнодоступні
RookieCoder

4

Я просто заглянув у свій код. В одній програмі я просто додаю елементи керування, але не вказуючи індекс, а коли закінчую, я просто перебираю стилі рядків і встановлюю тип розміру на AutoSize. Отже, просто додавання їх без зазначення індексів, здається, додає рядки за призначенням (за умови, що для 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.
Нік Алексєєв

0

Це чудово працює для додавання рядків та елементів керування в TableLayoutPanel.

Визначте порожню панель Tablelayout із 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 () як оптимізацію, але в цьому випадку, обертаючи мій код в них, рядки та стовпці поводяться правильно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.