0
votes

I'm programmatically adding panels (I call this panels blocks for better understanding) to another panel. Each of these blocks contain a title, a button to add a text box to the block and one staring text box.

This is the event I use to add the text boxes:

/// <summary>
/// Adds a text box to the button's parent
/// </summary>
protected void AddLabel_Click(object sender, EventArgs e)
{
    Button senderButton = (Button)sender;
    string parentId = senderButton.ID.Replace("_button","");
    Panel parent = (Panel)FindControl(update_panel, parentId);

    parent.Controls.Add(new TextBox
    {
        CssClass = "form-control canvas-label",
        ID = parent.ID + "_label" + parent.Controls.OfType<TextBox>().Count<TextBox>()
    });
}

However, every time I add a text box, the one I just created gets deleted

Edit This is how I ended up solving it (thanks to Don):

1) Keep a list of textboxes

Dictionary<string, List<string>> BlocksLabels
{
    get
    {
        if (ViewState["BlockLabels"] == null)
            ViewState["BlockLabels"] = new Dictionary<string, List<string>>();

        return ViewState["BlockLabels"] as Dictionary<string, List<string>>;
    }
    set { ViewState["BlockLabels"] = value; }
}

2) In the method that creates the blocks (called from Page_Load):

if (BlocksLabels.ContainsKey(block.ID))
{
    foreach (string label in BlocksLabels[block.ID])
        block.Controls.Add(new TextBox { ID = labelId });
}
else
{
    // Add one empty canvas label by default
    string labelId = block.ID + "_label0";
    BlocksLabels[block.ID] = new List<string>();
    BlocksLabels[block.ID].Add(labelId);
    block.Controls.Add(new TextBox { ID = labelId });
}

3) Finally, in the event that adds a new text box

Button senderButton = (Button)sender;
string parentId = senderButton.ID.Replace("_button", "");
Panel targetBlock = (Panel)FindControl(update_panel, parentId);

string labelId = targetBlock.ID + "_label" + BlocksLabels[targetBlock.ID].Count;
BlocksLabels[targetBlock.ID].Add(labelId);
targetBlock.Controls.Add(new TextBox { ID = labelId });
2

2 Answers

1
votes

In ASP.NET, if you create a control programmatically, you will need to re-create that control once again during post-backs.

So, the solution in your case would be to store the list of the Ids of the controls created and re-create them during the postback (preferably in the pageload event).

This is necessary for the Page control tree to line up with the viewstate stored.

1
votes

See the code below:

<asp:HiddenField runat="server" ID="hdnTbCnt" Value="0" />
<asp:Panel runat="server" ID="panel1">
</asp:Panel>
<asp:Button Text="Add TextBox" runat="server" OnClick="AddTextBox_Click" />

Code-behind:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        int tbCnt = Convert.ToInt32(hdnTbCnt.Value);

        for (int i = 1; i <= tbCnt; i++)
        {
            var tb = new TextBox()
            {
                ID = string.Format("txt{0}", i)
            };

            panel1.Controls.Add(tb);
        }
    }
}

protected void AddTextBox_Click(object sender, EventArgs e)
{
    int tbCount = Convert.ToInt32(hdnTbCnt.Value);

    var tb = new TextBox()
    {
        ID = string.Format("txt{0}", tbCount + 1)
    };

    panel1.Controls.Add(tb);

    hdnTbCnt.Value = (tbCount + 1).ToString();
}