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(...)), и это тоже работает.

Итак, выберите один из этих методов, они оба работают. Я помню головную боль, которую причиняла мне панель для сервировки стола.

OregonGhost
источник
Я попробую эти, чтобы увидеть, как они себя ведут!
Эш
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
EIV
источник
0

У меня была связанная проблема (именно так я нашел эту ветку), когда мои динамически добавленные стили строк и столбцов не вступали в силу. Обычно я рассматриваю SuspendLayout () / ResumeLayout () как оптимизацию, но в этом случае включение моего кода в них привело к правильному поведению строк и столбцов.

Начало мудрости
источник