Page 1 of 1

Dynamic Controls in ASP.NET: dynamcially adding Tabs to a page An overview on how to use dynamic controls in ASP.NET

#1 Frinavale  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 203
  • View blog
  • Posts: 776
  • Joined: 03-June 10

Posted 28 June 2010 - 10:07 AM

Overview
How to use dynamic controls is a commonly asked question and in ASP.NET it's not as simple or straightforward as they are in a windows desktop application. The reason for why dynamic controls are not easy to use in ASP.NET is because of the stateless environment that ASP.NET websites/applications run in. Also, typically new ASP.NET developers do not have a firm understanding of the ASP.NET life cycle and how it affects dynamic control.

ASP.NET Life Cycle and Dynamic Controls
The following a quick outline of happens when a browser requests an ASP.NET page:
  • The web browser makes a request to the web server for the page.
  • The web server receives the request and passes it to the ASP.NET for processing.
  • ASP.NET does authentication, authorization, and validation processes and then (if everything checks out ok) starts to execute your page.
  • Your Page's Init event is executed. In this event all of the controls and objects required to process the page request are instantiated (an instance of them is created).
  • Then the ViewState is loaded for your page and all of its controls. The ViewState contains data that is persisted between page requests (persisted = remembered). When the ViewState is loaded, events are also created based on ViewState the request information. Events are can only be created for objects that exist at this point. (For example: ViewState stores whether or not a CheckBox checked so that this state information can be remembered between page postbacks)
  • Your Page Load event is executed.
  • Your control events (like Button click events, or DropDownList selected index changed events etc.) are executed.
  • The Page PreRender event is executed. This is the last point that you can use the controls in your C# or VB.NET server-side code.
  • The Render event is executed. In this event all of the controls on the page are rendered as HTML. (Remember that web browsers use HTML to display data).
  • The response is sent to the browser and the page is unloaded, all of the controls, objects etc are destroyed. They are recreated the next page request


As you can see, all server-side objects/controls need to be recreated every time the page is requested (whether it be a postback to the server or the first time the page is loaded). If objects/controls do not exist when the ViewState is loaded, then the information that needs to be persisted (remembered) between postbacks will be lost, and any events that originated from the control will not be created. Many people do not understand this and so there are many questions about events not being executed, or data being lost for dynamically created controls like Buttons/CheckBoxes/TextBoxes/LinkButtons/DropDownLists/etc.

It is important that you instantiate your dynamic controls in the correct place in the ASP.NET page life cycle if you want to be able to persist data, or handle events for the dynamic controls. The correct place to do this is in the Page Init event. Just after the Page Init event is executed the ViewState is loaded with the persisted data and events generated for the control. So this means that, at a minimum, your dynamic control has to be instantiated in the Page Init event.


Dynamic Web User Controls
If you want to add a Web User Control dynamically into your page you must register that control with your page when you instantiate it. In order to do that ASP.NET has provided us with the Page.LoadControl() method. If you don't use this method you will run into problems with events in your application.

For example:
(C#)
MyWebUserControl myCtrl;
 
protected void Page_Init(object sender, EventArgs e){
    myCtrl = Page.LoadControl("~/MyWebUserControl.ascx");
    panel_forDisplayingMyControl.Controls.Add(myCtrl);
}


(VB.NET)
Private WithEvents myCtrl As MyWebUserControl
 
Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
    myCtrl = Page.LoadControl("~/MyWebUserControl.ascx")
    panel_forDisplayingMyControl.Controls.Add(myCtrl)
End Sub


Again, you must load the control in the Page_Init() method otherwise your web user control's ViewState will not be loaded properly and your events wont work properly: pretty much problems will occur.


Walkthrough Example: How to add Dynamic Tabs to the Page
This example demonstrates how to add tabs to the Tabs control that is part of the ASP.NET Ajax Toolkit Library. This toolkit is available free and it contains a lot of useful controls that help make life a little easier for ASP.NET developers. It provides ASP.NET developers with controls, like the Tabs control, are not native in ASP.NET. If you don't have this then you will have to download it in order to continue with this walkthrough example.

The first thing you need to do is create a new ASP.NET web application project.
By default your project will contain a Default.aspx page and we will be using this page for the walk through.

Once you have created the new ASP.NET web application, set up the Default.aspx page so that it contains a TabContainer(the Ajax Toolkit control that will contain the dynamic tabs).
  • If the Source view for the Default.aspx page is not open, open it.
  • Make sure that there is a ScriptManager on the page. (The ASP.NET Toolkit requires there to be a ScriptManager on the page to work).
  • You will also have to add a reference to the ASP.NET Ajax Control Toolkit to the project and then to the Default page:
    • Right click on your project name and click "Add reference"
    • Click the Browse tab in the Add Reference dialog and browse to the folder where the AjaxControlToolkit.dll resides
    • Select the AjaxControlToolkit.dll and click Ok to add the reference to the project

  • After you have added a reference to the Ajax Control Toolkit to the project you need to add a reference to the Ajax Control Tool kit to the Default.aspx page
  • After you've added a reference to the Ajax Control Toolkit to the page, add a TabContainer(which will contain the dynamic tabs) to the page.
  • Configure the TabContainer so that it posts back to the server when the active tab index is changed. When it posts back to the server have it call a method named "TabContainerContent_OnActiveTabChanged".
  • Add a button to the page. This button, when clicked, will dynamically add a TabPanel to the TabContainer.
  • Add a Label to the page which will display the current Tab ID when the tab index has changed.


Your page's source code should look like this:

(C#)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication2._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="sm" runat="server">
        </asp:ScriptManager>
        <cc1:TabContainer ID="TabContainerContent" runat="server" Height="150px" BackColor="White"
            AutoPostBack="True" OnActiveTabChanged="TabContainerContent_OnActiveTabChanged">
        </cc1:TabContainer>
        <asp:Button ID="addTab" Text="Add Tab" onclick="addTab_Click" runat="server" />
        <asp:Label ID="currentTabID" runat="server"></asp:Label>
    </div>
    </form>
</body>
</html>


(VB.NET)
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="WebApplication2._Default" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="sm" runat="server">
        </asp:ScriptManager>
        <cc1:TabContainer ID="TabContainerContent" runat="server" Height="150px" BackColor="White"
            AutoPostBack="True" OnActiveTabChanged="TabContainerContent_OnActiveTabChanged">
        </cc1:TabContainer>
        <asp:Button ID="addTab" Text="Add Tab" onclick="addTab_Click" runat="server" />
        <asp:Label ID="currentTabID" runat="server"></asp:Label>
    </div>
    </form>
</body>
</html>


Now lets go to the C#/VB.NET server-side code and dynamically add the TabPanels to the TabContainer when the button is clicked.

The first thing you need to (in your server side code) is declare some sort of container object that you can store the IDs of your Tabs in. This container object should have a page level scope. In this example I'm using a List<string> to store the IDs of my tabs in the following code:

(C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{
  public partial class _Default : System.Web.UI.Page
  {
    private List<string> dynamicTabIDs;
  }
}


(VB.NET)
Partial Public Class _Default
    Inherits System.Web.UI.Page
    Private dynamicTabIDs As List(Of String)
End Class


Now, because ASP.NET applications/websites are stateless I am going to store this container in Session so that I can recreate it the next time the page loads. I'm doing this in the Page PreRender event because I plan on adding items to it sometime during the Page LifeCycle which occurs after the PageLoad event:

(C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{
  public partial class _Default : System.Web.UI.Page
  {
    private List<string> dynamicTabIDs;
  
    protected void Page_PreRender(object sender, EventArgs e){
      //storing the dynamic tab IDs in session to recreate them next page postback
      Session["dynamicTabIDs"] = dynamicTabIDs;
    }
  }
}


(VB.NET)
Partial Public Class _Default
    Inherits System.Web.UI.Page
    Private dynamicTabIDs As List(Of String)

    Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
        'storing the dynamic tab IDs in session to recreate them next page postback'
        Session("dynamicTabIDs") = dynamicTabIDs
    End Sub
End Class


Now the list of TabIds is being stored somewhere so that I can retrieve it in order to recreate the dynamic TabPanels (tabs) the next time the page is requested.

Where do I need to recreate dynamic TabPanels?
In the Page Init event.

Why do I need to recreate the dynamic TabPanels in the Page Init Event and not in the Page Load event?

Well, because the Init event occurs before the Page's ViewState is loaded. The ViewState contains state information about all of the controls on the Page. If your controls do not exist at the time when ViewState is loaded then the ViewState for that control will not be loaded. Since ViewState helps in the creation of server side Events it is important that your controls exist at this point.

So, in the Page Init event retrieve the tab-IDs-container and if you can't then you'll have to create a new container for the tabs. Please note that you cannot use the Page's IsPostback property in this stage of the ASP.NET Page Life Cycle because the IsPostback property is set when ViewState is loaded, and the ViewState is loaded After the Page Init event; which means the IsPostback hasn't been set at this point and it will always return false.

Once you have retrieved the list of tab-IDs you need to recreate the tab associated with it (in the Page Init event):

(C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{

  public partial class _Default : System.Web.UI.Page
  {
    private List<string> dynamicTabIDs;

    protected void Page_Init(object sender, EventArgs e){
      //Checking to see if the dynamicTabIDs are in Session
      if (Session["dynamicTabIDs"] != null)
      {
        //if dynamicTabIDs are in session, recreating the Tabs
        //that are associated with the Tab IDs
        //and adding them to the TabContainer that will contain
        //all of the dynamic tabs.

        //retrieving the tab IDs from session:
        dynamicTabIDs = (List<string>)Session["dynamicTabIDs"];

        //looping through each TabID in session 
        //and recreating the TabPanel that is associated with that tabID
        foreach (string tabID in dynamicTabIDs)
        {
          //creating a new TabPanel that is associated with the TabID
          AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
          //Setting the ID property of the TabPanel
          tab.ID = tabID;
          //setting the TabPanel's HeaderText
          tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

          //creating a Label to add to the TabPanel...at this point you'll have to
          //create whatever controls are required for the tab...
          Label tabContent = new Label();
          //Giving the Label an ID
          tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString();
          //Setting the Label's text
          tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

          //Adding the Label to the TabPanel
          tab.Controls.Add(tabContent);
  
          //Adding the TabPanel to the TabContainer that contains the dynamic tabs
          TabContainerContent.Tabs.Add(tab);
        }
      }
      else
      { //Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
        dynamicTabIDs = new List<string>();
      }
    }
  
    protected void Page_PreRender(object sender, EventArgs e){
      //storing the dynamic tab IDs in session to recreate them next page postback
      Session["dynamicTabIDs"] = dynamicTabIDs;
    }
  
  }
}


(VB.NET)
Partial Public Class _Default
    Inherits System.Web.UI.Page
    Private dynamicTabIDs As List(Of String)

    Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        'Checking to see if the dynamicTabIDs are in Session'
        If (Session("dynamicTabIDs") IsNot Nothing) Then
            'if dynamicTabIDs are in session, recreating the Tabs'
            'that are associated with the Tab IDs'
            'and adding them to the TabContainer that will contain'
            'all of the dynamic tabs.'

            'retrieving the tab IDs from session:'
            dynamicTabIDs = CType(Session("dynamicTabIDs"), List(Of String))

            'looping through each TabID in session '
            'and recreating the TabPanel that is associated with that tabID'
            For Each tabID As String In dynamicTabIDs

                'creating a new TabPanel that is associated with the TabID'
                Dim tab As AjaxControlToolkit.TabPanel = New AjaxControlToolkit.TabPanel()
                'Setting the ID property of the TabPanel'
                tab.ID = tabID
                'setting the TabPanels HeaderText'
                tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

                'creating a Label to add to the TabPanel...at this point you will have to'
                'create whatever controls are required for the tab...'
                Dim tabContent As New Label()
                'Giving the Label an ID'
                tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString()
                'Setting the Labels text'
                tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

                'Adding the Label to the TabPanel'
                tab.Controls.Add(tabContent)

                'Adding the TabPanel to the TabContainer that contains the dynamic tabs'
                TabContainerContent.Tabs.Add(tab)
            Next

        Else
            'Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
            dynamicTabIDs = New List(Of String)
        End If

    End Sub

    Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
        'storing the dynamic tab IDs in session to recreate them next page postback'
        Session("dynamicTabIDs") = dynamicTabIDs
    End Sub
End Class


Ok, so far so good. Now we just need to dynamically add a new TabPanel to the Tab Content when the "addTab" button is clicked...easy enough.

In the "addTab" button's click event, create a new tab and add it to the TabContainer that contains the dynamic TabPanels and add it's ID to the dynamicTabIDs list:

(C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{

  public partial class _Default : System.Web.UI.Page
  {
    private List<string> dynamicTabIDs;
  
    protected void Page_Init(object sender, EventArgs e){
      //Checking to see if the dynamicTabIDs are in Session
      if (Session["dynamicTabIDs"] != null)
      {
        //if dynamicTabIDs are in session, recreating the Tabs
        //that are associated with the Tab IDs
        //and adding them to the TabContainer that will contain
        //all of the dynamic tabs.

        //retrieving the tab IDs from session:
        dynamicTabIDs = (List<string>)Session["dynamicTabIDs"];

        //looping through each TabID in session 
        //and recreating the TabPanel that is associated with that tabID
        foreach (string tabID in dynamicTabIDs)
        {
          //creating a new TabPanel that is associated with the TabID
          AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
          //Setting the ID property of the TabPanel
          tab.ID = tabID;
          //setting the TabPanel's HeaderText
          tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

          //creating a Label to add to the TabPanel...at this point you'll have to
          //create whatever controls are required for the tab...
          Label tabContent = new Label();
          //Giving the Label an ID
          tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString();
          //Setting the Label's text
          tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

          //Adding the Label to the TabPanel
          tab.Controls.Add(tabContent);

          //Adding the TabPanel to the TabContainer that contains the dynamic tabs
          TabContainerContent.Tabs.Add(tab);
        }
      }
      else
      { //Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
        dynamicTabIDs = new List<string>();
      }
    }
  
    protected void Page_PreRender(object sender, EventArgs e){
      Session["dynamicTabIDs"] = dynamicTabIDs;
    }
  
    protected void addTab_Click(object sender, EventArgs e)
    {
        //creating a new TabPanel
        AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
        //Setting the ID property of the TabPanel
        tab.ID = "tab" + Convert.ToString(TabContainerContent.Tabs.Count);
        //setting the TabPanel's HeaderText
        tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

        //creating a Label to add to the TabPanel...at this point you'll have to
        //create whatever controls are required for the tab...
        Label tabContent = new Label();
        //Giving the Label an ID
        tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString();
        //Setting the Label's text
        tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

        //Adding the Label to the TabPanel
        tab.Controls.Add(tabContent);

        //Adding the TabPanel to the TabContainer that contains the dynamic tabs
        TabContainerContent.Tabs.Add(tab);

        //Setting the ActiveTab to the newest tab added
        //Please be aware that you MUST set the ActiveTab or else you'll run into an exception
        TabContainerContent.ActiveTab = tab;
  
        //Adding the Tab's ID to the dynamicTabIDs list
        dynamicTabIDs.Add(tab.ID);
    }
  }
}


(VB.NET)
Partial Public Class _Default
    Inherits System.Web.UI.Page
    Private dynamicTabIDs As List(Of String)

    Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        'Checking to see if the dynamicTabIDs are in Session'
        If (Session("dynamicTabIDs") IsNot Nothing) Then
            'if dynamicTabIDs are in session, recreating the Tabs'
            'that are associated with the Tab IDs'
            'and adding them to the TabContainer that will contain'
            'all of the dynamic tabs.'

            'retrieving the tab IDs from session:'
            dynamicTabIDs = CType(Session("dynamicTabIDs"), List(Of String))

            'looping through each TabID in session '
            'and recreating the TabPanel that is associated with that tabID'
            For Each tabID As String In dynamicTabIDs

                'creating a new TabPanel that is associated with the TabID'
                Dim tab As AjaxControlToolkit.TabPanel = New AjaxControlToolkit.TabPanel()
                'Setting the ID property of the TabPanel'
                tab.ID = tabID
                'setting the TabPanels HeaderText'
                tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

                'creating a Label to add to the TabPanel...at this point you will have to'
                'create whatever controls are required for the tab...'
                Dim tabContent As New Label()
                'Giving the Label an ID'
                tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString()
                'Setting the Labels text'
                tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

                'Adding the Label to the TabPanel'
                tab.Controls.Add(tabContent)

                'Adding the TabPanel to the TabContainer that contains the dynamic tabs'
                TabContainerContent.Tabs.Add(tab)
            Next

        Else
            'Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
            dynamicTabIDs = New List(Of String)
        End If

    End Sub

    Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
        'storing the dynamic tab IDs in session to recreate them next page postback'
        Session("dynamicTabIDs") = dynamicTabIDs
    End Sub

    Protected Sub addTab_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles addTab.Click
        'creating a new TabPanel that is associated with the TabID'
        Dim tab As AjaxControlToolkit.TabPanel = New AjaxControlToolkit.TabPanel()
        'Setting the ID property of the TabPanel'
        tab.ID = "tab" + Convert.ToString(TabContainerContent.Tabs.Count)
        'setting the TabPanels HeaderText'
        tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

        'creating a Label to add to the TabPanel...at this point you will have to'
        'create whatever controls are required for the tab...'
        Dim tabContent As New Label()
        'Giving the Label an ID'
        tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString()
        'Setting the Labels text'
        tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

        'Adding the Label to the TabPanel'
        tab.Controls.Add(tabContent)

        'Adding the TabPanel to the TabContainer that contains the dynamic tabs'
        TabContainerContent.Tabs.Add(tab)

        'Setting the ActiveTab to the newest tab added'
        'Please be aware that you MUST set the ActiveTab or else you will run into an exception'
        TabContainerContent.ActiveTab = tab

        'Adding the Tab s ID to the dynamicTabIDs list'
        dynamicTabIDs.Add(tab.ID)
    End Sub
End Class


Lastly, we need to add code that handles the TabContainer's OnActiveTabChanged event. In the ASPX page markup we have specified that the method to call during this event is named "TabContainerContent_OnActiveTabChanged". This means that we have to add a method to the server side code with this name. In this method, to demonstrate that TabContainer's events work properly, we are simply going to set the "currentTabID" label's text to the Tab ID of the active tab:
(C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{

  public partial class _Default : System.Web.UI.Page
  {
    private List<string> dynamicTabIDs;

    protected void Page_Init(object sender, EventArgs e){
      //Checking to see if the dynamicTabIDs are in Session
      if (Session["dynamicTabIDs"] != null)
      {
        //if dynamicTabIDs are in session, recreating the Tabs
        //that are associated with the Tab IDs
        //and adding them to the TabContainer that will contain
        //all of the dynamic tabs.
  
        //retrieving the tab IDs from session:
        dynamicTabIDs = (List<string>)Session["dynamicTabIDs"];

        //looping through each TabID in session 
        //and recreating the TabPanel that is associated with that tabID
        foreach (string tabID in dynamicTabIDs)
        {
          //creating a new TabPanel that is associated with the TabID
          AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
          //Setting the ID property of the TabPanel
          tab.ID = tabID;
          //setting the TabPanel's HeaderText
          tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

          //creating a Label to add to the TabPanel...at this point you'll have to
          //create whatever controls are required for the tab...
          Label tabContent = new Label();
          //Giving the Label an ID
          tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString();
          //Setting the Label's text
          tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

          //Adding the Label to the TabPanel
          tab.Controls.Add(tabContent);

          //Adding the TabPanel to the TabContainer that contains the dynamic tabs
          TabContainerContent.Tabs.Add(tab);
        }
      }
      else
      { //Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
        dynamicTabIDs = new List<string>();
      }
    }
  
    protected void Page_PreRender(object sender, EventArgs e){
      Session["dynamicTabIDs"] = dynamicTabIDs;
    }

    protected void addTab_Click(object sender, EventArgs e)
    {
        //creating a new TabPanel t
        AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
        //Setting the ID property of the TabPanel
        tab.ID = "tab" + Convert.ToString(TabContainerContent.Tabs.Count);
        //setting the TabPanel's HeaderText
        tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

        //creating a Label to add to the TabPanel...at this point you'll have to
        //create whatever controls are required for the tab...
        Label tabContent = new Label();
        //Giving the Label an ID
        tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString();
        //Setting the Label's text
        tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();

        //Adding the Label to the TabPanel
        tab.Controls.Add(tabContent);

        //Adding the TabPanel to the TabContainer that contains the dynamic tabs
        TabContainerContent.Tabs.Add(tab);

        //Setting the ActiveTab to the newest tab added
        //Please be aware that you MUST set the ActiveTab or else you'll run into an exception
        TabContainerContent.ActiveTab = tab;
  
        //Adding the Tab's ID to the dynamicTabIDs list
        dynamicTabIDs.Add(tab.ID);
    }

    protected void TabContainerContent_OnActiveTabChanged(object sender, EventArgs e) {
      //displaying the ID of the active tab
      currentTabID.Text=TabContainerContent.ActiveTab.ID;
    }

  }
}


(VB.NET)
Partial Public Class _Default
    Inherits System.Web.UI.Page
    Private dynamicTabIDs As List(Of String)

    Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        'Checking to see if the dynamicTabIDs are in Session'
        If (Session("dynamicTabIDs") IsNot Nothing) Then
            'if dynamicTabIDs are in session, recreating the Tabs'
            'that are associated with the Tab IDs'
            'and adding them to the TabContainer that will contain'
            'all of the dynamic tabs.'

            'retrieving the tab IDs from session:'
            dynamicTabIDs = CType(Session("dynamicTabIDs"), List(Of String))

            'looping through each TabID in session '
            'and recreating the TabPanel that is associated with that tabID'
            For Each tabID As String In dynamicTabIDs

                'creating a new TabPanel that is associated with the TabID'
                Dim tab As AjaxControlToolkit.TabPanel = New AjaxControlToolkit.TabPanel()
                'Setting the ID property of the TabPanel'
                tab.ID = tabID
                'setting the TabPanels HeaderText'
                tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

                'creating a Label to add to the TabPanel...at this point you will have to'
                'create whatever controls are required for the tab...'
                Dim tabContent As New Label()
                'Giving the Label an ID'
                tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString()
                'Setting the Labels text'
                tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

                'Adding the Label to the TabPanel'
                tab.Controls.Add(tabContent)

                'Adding the TabPanel to the TabContainer that contains the dynamic tabs'
                TabContainerContent.Tabs.Add(tab)
            Next

        Else
            'Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
            dynamicTabIDs = New List(Of String)
        End If

    End Sub

    Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
        'storing the dynamic tab IDs in session to recreate them next page postback'
        Session("dynamicTabIDs") = dynamicTabIDs
    End Sub

    Protected Sub addTab_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles addTab.Click
        'creating a new TabPanel that is associated with the TabID'
        Dim tab As AjaxControlToolkit.TabPanel = New AjaxControlToolkit.TabPanel()
        'Setting the ID property of the TabPanel'
        tab.ID = "tab" + Convert.ToString(TabContainerContent.Tabs.Count)
        'setting the TabPanels HeaderText'
        tab.HeaderText = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

        'creating a Label to add to the TabPanel...at this point you will have to'
        'create whatever controls are required for the tab...'
        Dim tabContent As New Label()
        'Giving the Label an ID'
        tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString()
        'Setting the Labels text'
        tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString()

        'Adding the Label to the TabPanel'
        tab.Controls.Add(tabContent)

        'Adding the TabPanel to the TabContainer that contains the dynamic tabs'
        TabContainerContent.Tabs.Add(tab)

        'Setting the ActiveTab to the newest tab added'
        'Please be aware that you MUST set the ActiveTab or else you will run into an exception'
        TabContainerContent.ActiveTab = tab

        'Adding the Tab s ID to the dynamicTabIDs list'
        dynamicTabIDs.Add(tab.ID)
    End Sub

    Protected Sub TabContainerContent_OnActiveTabChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TabContainerContent.ActiveTabChanged
        'displaying the ID of the active tab'
        currentTabID.Text = TabContainerContent.ActiveTab.ID
    End Sub
End Class



One thing that I have to clarify is why I chose to use to store the list of TabIDs instead of a list of TabPanels....

When I tried to use store TabPanels into Session I ran into a bunch of problems. The errors I was getting were complaining about scripts being rendered before the Render event, or it was complaining about controls being modified in when they weren't allowed to.

The reason must have something to do with saving tabs into Session. The only way I was able to get around this was to store a list of tab ID's instead of a list of TabPanels in session. In other words, I could not use List<AjaxControlTollkit.TabPanel> dynamicPanels...I had to use private List<string> dynamicTabIDs;

I hope that this article was helpful to you :)
Happy coding!

-Frinny

Is This A Good Question/Topic? 0
  • +

Replies To: Dynamic Controls in ASP.NET: dynamcially adding Tabs to a page

#2 CCDSystems  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 21-August 14

Posted 21 August 2014 - 09:07 AM

Quite good post, as it's helped me get going in the right direction. Thank you!

However, your 5th, 6th and 7th code blocks look identical, which causes some confusion. It wasn't until I looked more closely that I saw that you were adding on to your code block each time, it's just that the first 25 lines of each code block are identical.

A clearer way to present this would be for each code clock to highlight only the newly-added code. If you want to save the reader from a lot of cut-and-pasting, you can additionally present the complete project in a code-block at the end. Please ensure this code-block does not have line-numbers, or the reader will have to manually delete the numbers one-at-a-time.

A great post. Again, thank you!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1