Thursday, 6 July 2017

Maintain The State Of Dynamic Added User Control On Each PostBack


Introduction
In this article we will learn how to maintain the state of dynamically created controls in asp.net using c#.  Retain the state of dynamic created controls or maintain the data of dynamic created/ added user control on postback in asp.net. Maintain the dynamic control events, data during postback in asp.net

Previous Updates
In previous articles we have learnt Load the Usercontrol In Aspx Page.  Get TextBox , Dropdown, CheckBox  control Values In Aspx.cs Page From User Control Using C#.  Binding Data To HTML using AngularJS.  CRUD operation using AngularJS.


Problem With Dynamic Created Controls
When you working with dynamic controls in any WebApplication then the biggest task is to understand the postback and maintain the state of newly created dynamic control at the time of Postback.
If you are not familiar with the postback then  you will get the best answer here.

Postback is a process when you submit a asp.net  web page to the server for processing. In other words -
Postback is a process of sending  roundtrip request from Client Machine/ Browser to server for processing the request  and  then back to the client. 

For Example if you are working with any website which have registration page or any form filling page like a login page. There is validation used in that Login page. 
                    Now suppose when you click on login button for performing login operation and application have validations for check the requested mail id and Password is correct or not  , if it is failed then server sends the validation message back to client and remain on the same login page. That's the postback when the server sends back the message to client.


Asp.net  controls state manage by their viewstate. All asp.net controls maintain their data in viewstate during postback. But when you are with dynamic controls the will not able to maintain its state during postback and their data lost.
Means if you fill all your detail in web registration form and click on submit then after postback if the page again comes back with any validation error issue then all of your filled data lost from all textboxes and other controls on form. This only happens if these controls will not maintaining there state. 
Same data lost issue with our dynamic controls. Cause they dont have any viewstate to maintain their data .So here we learn how to overcome from this problem and retain the data as like normal controls.


Generate Dynamic Controls And Maintain State
Here i am using the same example which i use in my previous updates Load the user control in aspx page and get TextBox , Dropdown, CheckBox  control Values In Aspx.cs Page From User Control Using C# .
UserControl Code ---
<%@ Control Language="C#" AutoEventWireup="true" 
CodeFile="uc_MyUserControl.ascx.cs" Inherits="UserControls_uc_MyUserControl" %>

 <table>
     <thead> <h3> User Control Loaded </h3></thead>
   <tr>
      <td> <asp:Label ID="lblName" Text="First Name" runat="server"></asp:Label> </td>
      <td> <asp:TextBox ID="txtFName" Text="" runat="server"></asp:TextBox> </td>
   </tr>
   <tr>
     <td> <asp:Label ID="lblGender" Text="Gender" runat="server"></asp:Label> </td>
     <td> <asp:DropDownList ID="ddlGender" runat="server" Width="173px">
                            <asp:ListItem Text="--Select--" Value="0"></asp:ListItem>
                            <asp:ListItem Text="Male" Value="M"></asp:ListItem>
                            <asp:ListItem Text="Female" Value="F"></asp:ListItem>
                        </asp:DropDownList> </td>
    </tr>
     <tr>
          <td> <asp:Label ID="lblAdi" Text="Adult" runat="server"></asp:Label> </td>
         <td><asp:CheckBox ID="chkAdult" runat="server" Checked="false" /></td>
     </tr>
</table>

Aspx Code ---
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="MyWebForm1.aspx.cs" 
    Inherits="UserControls_MyWebForm1" %>
<%@ Register Src="~/UserControls/uc_MyUserControl.ascx" 
    TagPrefix="uc1" TagName="uc_MyUserControl" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server"> </head>
<body>
    <form id="form1" runat="server">
         <div>
            <asp:Button ID="btnGenrate" runat="server" Text="Generate Dynamic Controls"
                       OnClick="btnGenrate_Click" />
        </div>
     <div>
         <asp:Panel ID="pnlMyUC" runat="server">
            <uc1:uc_MyUserControl runat="server" ID="uc_MyUserControl" />
             </asp:Panel>
     </div>
    </form>
</body>
</html>

Now the main code where we generate the dynamic controls and maintain their values during postback. 
Aspx.cs Code  ---
#region Gloabal Variables
    private Dictionary<Guid, string> tempList = new Dictionary<Guid, string>();

    public Dictionary<Guid, string> UcList
    {
        get { return ViewState["MyUcIds"] != null 
                 ? (Dictionary<Guid, string>)ViewState["MyUcIds" : new Dictionary<Guidstring>(); }
        set { ViewState["MyUcIds"] = value; }
    }
    #endregion

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadControl();
        else
            InitializeUC();
    }

    public void LoadControl()
    {
        UserControls_uc_MyUserControl objUC = 
                             (UserControls_uc_MyUserControl)Page.FindControl("uc_MyUserControl");
        pnlMyUC.Controls.Add(objUC);
    }

   //Initialize the control during postback and retain their values
    public void InitializeUC()
    {
        int index = 1;
        foreach (var item in UcList)
        {
            var myUc =
 (UserControls_uc_MyUserControl)LoadControl("~/UserControls/uc_MyUserControl.ascx");
            myUc.ID = item.Value;
            pnlMyUC.Controls.AddAt(index, myUc);
            index++;
        }
    }

    protected void btnGenrate_Click(object sender, EventArgs e)
    {
        UserControls_uc_MyUserControl myUc;
        Guid lastKey = Guid.NewGuid();      //Generate random keys for dynamic controls
        tempList = UcList;
        if (UcList.Count > 0)
        {
            lastKey = UcList.Last().Key;
            lastKey = Guid.NewGuid();
        }
        tempList[lastKey] = "objUc" + lastKey.ToString().Replace('-''_');
        UcList = tempList;
        myUc =
 (UserControls_uc_MyUserControl)LoadControl("~/UserControls/uc_MyUserControl.ascx");
        myUc.ID = UcList[lastKey];
        pnlMyUC.Controls.Add(myUc);
    }
In this code i define a tempList variable of Dictionary type for containing key and value of usercontrol. and a UcList type property which required for store usercontrol data temporarily on InitializeUC method.
When our page first time loads without postback it will call the LoadControl Method and loads the Usercontrol first time but after this when clicking on Genrate Dynamic Control button it will always call the InitializeUC method on postback true condition.
InitializeUC method reads the user controls list from viewstate and assigning back to the aspx page thats why our values will remain same during postback or any event click.

OutPut 





7 comments: