Solved

Dynamically created controls lose state on postback

Posted on 2014-03-28
4
863 Views
Last Modified: 2014-04-29
My dynamically created controls are losing state.

Here is the process...

1 PageLoads
2 On DDLSelectedIndexChanged controls are created dynamically
3 On ButtonClick I want to read the values from the controls but they are gone

This makes sense but I'm not sure how to address it. Below is a code sample I wrote that exposes the problem I'm running in to. Just try to run it and you will see what I mean.

<%@ Page Language="C#" %>

<!DOCTYPE html>

<script runat="server">


    protected void Page_Load(object sender, EventArgs e)
    {
        ButtonSubmit.Visible = false;    
    }
    
    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (DropDownList1.SelectedIndex == 0)
            return;
        
        FillTableControls();
        ButtonSubmit.Visible = true;
    }

    protected void FillTableControls()
    {
        AddTextBoxRow("1", "Name");
        AddTextBoxRow("2", "Address");
        AddTextBoxRow("3", "Email");
    }

    protected void AddTextBoxRow(string suffix, string labelText)
    {
        TableRow row = new TableRow();
        TableCell cell1 = new TableCell();
        TableCell cell2 = new TableCell();

        System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label();
        System.Web.UI.WebControls.TextBox textbox = new System.Web.UI.WebControls.TextBox();

        label.ID = "Label" + suffix;
        label.Text = labelText;
        textbox.ID = "TextBox" + suffix;
        cell1.Width = 200;
        cell1.Controls.Add(label);
        cell2.Controls.Add(textbox);
        row.Cells.Add(cell1);
        row.Cells.Add(cell2);

        TableControls.Rows.Add(row);
    }


    protected void ButtonSubmit_Click(object sender, EventArgs e)
    {
        for (int i = 1; i < 4; i++)
        {
            string controlName = "TextBox" + i.ToString();
            TextBox t = (TextBox)this.TableControls.FindControl(controlName);
            LabelMessage.Text += t.Text + ", ";
        }
    }
    
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" >
            <asp:ListItem>Select something...</asp:ListItem>
            <asp:ListItem>This will do</asp:ListItem>
        </asp:DropDownList>
        <br />
        <br />
        <asp:Table ID="TableControls" runat="server">
        </asp:Table>
        <br />
        <asp:Button ID="ButtonSubmit" runat="server" Text="Postback" OnClick="ButtonSubmit_Click"  />
    
        <br />
        <br />
        <asp:Label ID="LabelMessage" runat="server"></asp:Label>
    
    </div>
    </form>
</body>
</html>

Open in new window

0
Comment
Question by:tatton777
  • 2
4 Comments
 
LVL 21

Expert Comment

by:Dale Burrell
Comment Utility
I think you have to recreate the control tree that was sent to the browsers earlier in the event chain. I think you have to create it on postback during the onload event at the latest for the ASP.NET framework to load viewstate data for the controls etc.

Then you can modify the control tree again later in your onclick event.
0
 
LVL 2

Expert Comment

by:GowthamNatarajan
Comment Utility
Try this...
Creating a static table and binding it to panel helps....

<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">


    static Table tab = new Table();

    protected void Page_Load(object sender, EventArgs e)
    {
        ButtonSubmit.Visible = false;
        if (IsPostBack)
        {
         pan.Controls.Add(tab);
        }
        else
        {
            pan.Controls.Remove(tab);
        }
    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (DropDownList1.SelectedIndex == 0)
            return;

        FillTableControls();
        ButtonSubmit.Visible = true;
    }

    protected void FillTableControls()
    {
        AddTextBoxRow("1", "Name");
        AddTextBoxRow("2", "Address");
        AddTextBoxRow("3", "Email");
    }

    protected void AddTextBoxRow(string suffix, string labelText)
    {
        TableRow row = new TableRow();

        TableCell cell1 = new TableCell();
        TableCell cell2 = new TableCell();
        System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label();
        System.Web.UI.WebControls.TextBox textbox = new System.Web.UI.WebControls.TextBox();

        label.ID = "Label" + suffix;
        label.Text = labelText;
        textbox.ID = "TextBox" + suffix;
        cell1.Width = 200;
        cell1.Controls.Add(label);
        cell2.Controls.Add(textbox);
        row.Cells.Add(cell1);
        row.Cells.Add(cell2);

        tab.Rows.Add(row);

        pan.Controls.Add(tab);
    }

    protected void ButtonSubmit_Click(object sender, EventArgs e)
    {
        for (int i = 1; i < 4; i++)
        {
            string controlName = "TextBox" + i.ToString();
            TextBox t = (TextBox)FindControl(controlName);
            LabelMessage.Text += t.Text + ", ";
        }
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
   
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" >
            <asp:ListItem>Select something...</asp:ListItem>
            <asp:ListItem>This will do</asp:ListItem>
        </asp:DropDownList>
        <br />
        <br />
        <asp:Panel ID="pan" runat="server"></asp:Panel>
        <br />
        <asp:Button ID="ButtonSubmit" runat="server" Text="Postback" OnClick="ButtonSubmit_Click"  />
   
        <br />
        <br />
        <asp:Label ID="LabelMessage" runat="server"></asp:Label>
   
    </div>
    </form>
   </body>
</html>
0
 
LVL 1

Accepted Solution

by:
tatton777 earned 0 total points
Comment Utility
I ended up getting help elsewhere. You have to load the table with the controls on EVERY POSTBACK once the set of controls is instantiated. You can do this on the Page_Load or the Page_Init, it doesn't matter.

    //==================================================
    // Page_Load()
    //==================================================
    protected void Page_Load(object sender, EventArgs e)
    {
        if(!Page.IsPostBack)
        {

        }
        if(sv.FillPdfPageFormControls != null)
            LoadTableWithPdfControls(sv.FillPdfPageFormControls);
    }

    //==================================================
    // LoadTableWithPdfControls()
    //==================================================
    protected void LoadTableWithPdfControls(DataTable formContols)
    {
        int rowCount = 1;

        foreach (DataRow r in formContols.Rows)
        {
            string controlType = r["ControlType"].ToString().ToLower().Trim();

            if (controlType == "spacer")
            {
                TableRow row = new TableRow();
                TableCell cell = new TableCell();
                cell.ColumnSpan = 2;
                cell.Text = " ";
                row.Cells.Add(cell);                
                
                TableControls.Rows.Add(row);
                TableControls.Rows.Add(row);
            }

            if (controlType == "label")
            {
                TableRow row = new TableRow();
                TableCell cell = new TableCell();

                System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label();
                label.Text = r["ControlText"].ToString();
                label.ID = r["ControlName"].ToString();
                cell.ColumnSpan = 2;
                cell.Controls.Add(label);
                row.Cells.Add(cell);
                TableControls.Rows.Add(row);
            }

            if (controlType == "textbox")
            {
                TableRow row = new TableRow();
                TableCell cell1 = new TableCell();
                TableCell cell2 = new TableCell();

                System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label();
                System.Web.UI.WebControls.TextBox textbox = new System.Web.UI.WebControls.TextBox();
                label.ID = "Label" + rowCount.ToString();
                label.Text = r["ControlText"].ToString();

                //TextBox wk = (TextBox)this.TableControls.FindControl(r["controlName"].ToString());

                textbox.ID = r["ControlName"].ToString();

                cell1.Width = 200;
                cell1.Controls.Add(label);
                cell2.Controls.Add(textbox);
                row.Cells.Add(cell1);
                row.Cells.Add(cell2);

                TableControls.Rows.Add(row);
            }

            if (controlType == "checkbox")
            {
                TableRow row = new TableRow();
                TableCell cell1 = new TableCell();
                TableCell cell2 = new TableCell();

                System.Web.UI.WebControls.CheckBox checkbox = new System.Web.UI.WebControls.CheckBox();

                checkbox.Text = r["ControlText"].ToString();
                checkbox.ID = r["ControlName"].ToString();

                cell2.Controls.Add(checkbox);
                row.Cells.Add(cell1);
                row.Cells.Add(cell2);
                TableControls.Rows.Add(row);
            }
            rowCount += 1;
        }
    }

Open in new window

0
 
LVL 1

Author Closing Comment

by:tatton777
Comment Utility
Hello,
This question is almost exactly the same as the other that I answered. It required the same answer.

I found the answer to my question somewhere besides EE and decided to share it with the community.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

In .NET 2.0, Microsoft introduced the Web Site.  This was the default way to create a web Project in Visual Studio 2005.  In Visual Studio 2008, the Web Application has been restored as the default web Project in Visual Studio/.NET 3.x The Web Si…
Introduction This article shows how to use the open source plupload control to upload multiple images. The images are resized on the client side before uploading and the upload is done in chunks. Background I had to provide a way for user…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now