Search code examples
asp.netvb.netwebformsviewstate

How to dynamically add controls and preserve Viewstate?


I'm attempting to use Controls.AddAt(), but it apparently breaks controls at later indexes:

Here's my minimal example:

Aspx put in a form:

<asp:DropDownList runat="server" ID="ddl" />
<asp:Button Text="text" runat="server" OnClick="Unnamed2_Click" />

Code Behind:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not IsPostBack Then
        ddl.Items.Add("Click the button")   
        'Controls.Add(New HyperLink) 'Works fine, but is put at end of collection.
        'Controls.AddAt(2 ,New HyperLink) 'Is also safe but I wanted the control first
        Controls.AddAt(0, New HyperLink) 'ddl loses it's item after postback
    End If
End Sub

On the first postback of the page after calling AddAt, the DropDownList loses it's item. It doesn't matter what kind of control I add even HTMLControls. Viewstate is not disabled.

How do I dynamically add controls without breaking others?


Solution

  • If you used a PlaceHolder to add your HyperLink into, it would not mess up the rest of the page:

    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
    <asp:DropDownList ID="ddl" EnableViewState="true" runat="server" />
    <asp:Button ID="bn1" Text="text" OnClick="Unnamed2_Click" runat="server" />
    

    With code like

    Protected Sub Unnamed2_Click(sender As Object, e As EventArgs) Handles bn1.Click
        Dim newItem = "Click the button" & DateTime.Now.ToString("HH:mm:ss")
        ddl.Items.Add(newItem)
        ddl.SelectedIndex = ddl.Items.Count - 1
        PlaceHolder1.Controls.Add(New HyperLink With {.ID = "hyp", .Text = "Hyperlink here"})
    
    End Sub
    

    And always give your asp:Controls an ID if they take one.