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.Fill они все еще кажутся слишком большими / маленькими).

Есть ли у кого-нибудь рабочий пример добавления строк и элементов управления во время выполнения?


Добавление 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
Спасибо за идею для пустой строки-заполнителя! Решил мои проблемы с размером.
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 (); когда форма загружается.
Джон

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 (среди Top, Middle и Bottom) заставляли казаться, что таблица каким-то странным образом генерирует дополнительные строки, но это не так. Эта штука работает довольно хорошо, когда вы в ней разбираетесь, но добраться туда было болезненно!
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 и измените модификаторы с частных на общедоступные
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.