Alp Eren Dursun
Alp Eren Dursun

Reputation: 13

C# Form Application Dynamically Added Elements Positioning

Firstly I am sorry for may poor language. I am new to C# and trying to build an simple form application. When button clicked new textboxes and labels will be put in the window. Here is the problem. When i scrooled right and clicked button, new added elements is located right of the other elements. Can you help me with this problem.

Normal Added Elements

When Scrolled To Right

Last Positioning

static int formNo = 1;

private void btnEkle_Click(object sender, EventArgs e)
{
    TextBox isimTb = new TextBox();
    TextBox fiyatTb = new TextBox();
    Label urunLbl = new Label();

    int positionNo = formNo;

    isimTb.Name = "isimBox" + formNo.ToString();
    isimTb.Location = new Point(125, ((positionNo - 1) * 25));
    isimTb.Width = 200;
    isimTb.Text = "Ürün İsmini Giriniz";

    fiyatTb.Name = "fiyatBox" + formNo.ToString();
    fiyatTb.Left = 350;
    fiyatTb.Top = (positionNo - 1) * 25;
    fiyatTb.Width = 200;
    fiyatTb.Text = "Ürün Fiyatını Giriniz";

    urunLbl.Name = "label" + formNo.ToString();
    urunLbl.Text = formNo.ToString() + ". Ürün";
    urunLbl.Left = 10;
    urunLbl.Top = (positionNo - 1) * 25;
    urunLbl.Width = 100;


    this.Controls.Add(urunLbl);
    this.Controls.Add(isimTb);
    this.Controls.Add(fiyatTb);

    btnEkle.Top = (positionNo - 1) * 25 + 50;
    btnKaydet.Top = (positionNo - 1) * 25 + 50;

    formNo++;
}

Upvotes: 1

Views: 95

Answers (2)

NineBerry
NineBerry

Reputation: 28499

Consider the values of the AutoScrollPosition property when adding the controls.

/// <summary>
/// Make a point that gives a location at the given coordinates in the form
/// independent of the current scroll position
/// </summary>
private Point MakeAbsolutePosition(int x, int y)
{
    Point result = new Point(x + AutoScrollPosition.X, y + AutoScrollPosition.Y);

    return result;
}

private void btnEkle_Click(object sender, EventArgs e)
{
    TextBox isimTb = new TextBox();
    TextBox fiyatTb = new TextBox();
    Label urunLbl = new Label();

    int positionNo = formNo;

    isimTb.Name = "isimBox" + formNo.ToString();
    isimTb.Location = MakeAbsolutePosition(125, ((positionNo - 1) * 25));
    isimTb.Width = 200;
    isimTb.Text = "Ürün İsmini Giriniz";

    fiyatTb.Name = "fiyatBox" + formNo.ToString();
    fiyatTb.Location = MakeAbsolutePosition(350, (positionNo - 1) * 25);
    fiyatTb.Width = 200;
    fiyatTb.Text = "Ürün Fiyatını Giriniz";

    urunLbl.Name = "label" + formNo.ToString();
    urunLbl.Text = formNo.ToString() + ". Ürün";
    urunLbl.Location = MakeAbsolutePosition(10, (positionNo - 1) * 25);
    urunLbl.Width = 100;

    this.Controls.Add(urunLbl);
    this.Controls.Add(isimTb);
    this.Controls.Add(fiyatTb);

    // TODO: Use the correct x values here
    btnEkle.Location = MakeAbsolutePosition(100, (positionNo - 1) * 25 + 50);
    btnKaydet.Location =MakeAbsolutePosition(200,  (positionNo - 1) * 25 + 50);

    formNo++;
}

The documentation for the AutoScrollPosition property says:

When adding controls programmatically to a form, use the AutoScrollPosition property to position the control either inside or outside of the current viewable scroll area.

The approach using a LayoutPanel (e.g. TableLayoutPanel or FlowLayoutPanel) as shown in other answers is better. You should use that one if possible.

Upvotes: 0

remondo
remondo

Reputation: 388

You don't have a layout container, e.g. TableLayoutPanel. These layout containers will help you position your dynamically added controls. I'm pasting some sample code I did for a dynamically added controls:

internal void AddControl(Models.CdConfig selectedCd)
    {
        SelectedCds.Add(selectedCd);
        if (selectedCd.DataType == CdType.Combo || selectedCd.DataType == CdType.Choice)
        {
            subItemHeight = 23;
        }
        else
        {
            subItemHeight = 30;
        }
        int currItemRowCount = getItemRowCount(selectedCd);
        Panel controlPanel = new Panel() // the panel that is visible
        {
            BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle,
            Location = new Point(3,3),
            Size = new Size(this.Size.Width - margin * 2 * 2 - scrollbarbuff, itemHeight + subItemHeight * currItemRowCount)
        };

        TableLayoutPanel t1 = new TableLayoutPanel() // main tlp
        {
            ColumnCount = 1,
            RowCount = 2,
            Size = new Size(this.Size.Width - margin * 2 * 2 - scrollbarbuff, itemHeight + subItemHeight * currItemRowCount)
        };
        t1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
        t1.RowStyles.Add(new RowStyle(SizeType.Absolute, itemHeight));
        t1.RowStyles.Add(new RowStyle(SizeType.AutoSize));

        TableLayoutPanel tHeader = new TableLayoutPanel() // label and delete button
        {
            ColumnCount = 2,
            RowCount = 1,
            Size = new Size(this.Size.Width - margin * 2 * 2 - scrollbarbuff, itemHeight)
        };
        tHeader.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 80F));
        tHeader.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
        tHeader.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
        t1.Controls.Add(tHeader, 0, 0);

        // Add the label
        Label lbl = new Label()
        {
            Text = selectedCd.DisplayName,
            Anchor = AnchorStyles.Left | AnchorStyles.Top,
            Margin = new Padding(0, 3 * 2, 0, 0)
        };
        tHeader.Controls.Add(lbl, 0, 0);

        Button deleteBtn = new Button()
        {
            Text = "Delete",
            Anchor = AnchorStyles.Right | AnchorStyles.Top,
            Margin = new Padding(0, 2, 3 * 2, 0)
        };
        deleteBtn.Tag = controlPanel;
        deleteBtn.Click += HandleDelete;
        tHeader.Controls.Add(deleteBtn, 1, 0);
        controlPanel.Controls.Add(t1);

        // For the control
        TableLayoutPanel tControl = CreateCdControl(selectedCd, currItemRowCount);

        t1.Controls.Add(tControl, 0, 1);

        this.Controls.Add(controlPanel);
        controlPanel.Tag = selectedCd; // for convenience
    }

Upvotes: 1

Related Questions