5 Replies - 23627 Views - Last Post: 18 June 2010 - 09:52 AM Rate Topic: -----

#1 Anjut  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 21-November 09

Dynamically adding tab panels to tab containers

Posted 23 November 2009 - 05:21 AM

I want to dynamically add tabs on page to Tabcontainer1 on Button Click Event.Two Tabs are added from before. I have written the following code but it works for only one time. The second time I added I got the error.

The code I wrote for adding new tab is as follows:
protected void Button1_Click(object sender, EventArgs e)
{
tabcount = tabcount + 1;		
		AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();				
		TabContainer1.Tabs.Add(tab);		
		tab.ID = "tab" + Convert.ToString(tabcount);
}


Tab count is initialized before and I am incrementing it before adding new tab.

The error I get on adding the tab second time is:

Specified argument was out of the range of valid values.
Parameter name: value


Any help will be appreciated. Thank You.

Is This A Good Question/Topic? 0
  • +

Replies To: Dynamically adding tab panels to tab containers

#2 Jayman  Icon User is offline

  • Student of Life
  • member icon

Reputation: 418
  • View blog
  • Posts: 9,532
  • Joined: 26-December 05

Re: Dynamically adding tab panels to tab containers

Posted 23 November 2009 - 08:50 AM

Set all the properties of a control before you add it.

protected void Button1_Click(object sender, EventArgs e)
{
		tabcount = tabcount + 1;		
		AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
		tab.ID = "tab" + Convert.ToString(tabcount);				
		TabContainer1.Tabs.Add(tab);			  
}


Which line is throwing the error message?
Was This Post Helpful? 0
  • +
  • -

#3 Anjut  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 21-November 09

Re: Dynamically adding tab panels to tab containers

Posted 28 November 2009 - 04:44 AM

View PostJayman, on 23 Nov, 2009 - 07:50 AM, said:

Set all the properties of a control before you add it.

protected void Button1_Click(object sender, EventArgs e)
{
		tabcount = tabcount + 1;		
		AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
		tab.ID = "tab" + Convert.ToString(tabcount);				
		TabContainer1.Tabs.Add(tab);			  
}


Which line is throwing the error message?

Thank You Jayman it does not show me the line, I first get that there is no source code available giving me the option of show disassembly and then when i don't accept it it shows me the error, it does not specify any line that error box is displayed. Which propertie of tab should i set as i have set only the id of tab container

This post has been edited by Anjut: 28 November 2009 - 04:46 AM

Was This Post Helpful? 0
  • +
  • -

#4 Guest_Harish*


Reputation:

Re: Dynamically adding tab panels to tab containers

Posted 16 June 2010 - 02:55 PM

View PostAnjut, on 28 November 2009 - 03:44 AM, said:

View PostJayman, on 23 Nov, 2009 - 07:50 AM, said:

Set all the properties of a control before you add it.

protected void Button1_Click(object sender, EventArgs e)
{
		tabcount = tabcount + 1;		
		AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
		tab.ID = "tab" + Convert.ToString(tabcount);				
		TabContainer1.Tabs.Add(tab);			  
}


Which line is throwing the error message?

Thank You Jayman it does not show me the line, I first get that there is no source code available giving me the option of show disassembly and then when i don't accept it it shows me the error, it does not specify any line that error box is displayed. Which propertie of tab should i set as i have set only the id of tab container


Harish: Even I am facing the same issue any help really appreciated..
Was This Post Helpful? 0

#5 Guest_harish*


Reputation:

Re: Dynamically adding tab panels to tab containers

Posted 16 June 2010 - 02:56 PM

Harish: lxm96641@gsk.com
Was This Post Helpful? 0

#6 Frinavale  Icon User is offline

  • D.I.C Addict
  • member icon

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

Re: Dynamically adding tab panels to tab containers

Posted 18 June 2010 - 09:52 AM

The error is occurring because the tab no longer exists the second time.

Remember that ASP.NET applications and websites operate in a Stateless Environment.

In other words, after your page is finished processing the request all of the objects that were used for processing are destroyed.

So, when the next page request occurs the objects required to do the page processing are recreated.

In your case, however, you are declaring a Tab within a Button Click event....so that means that when the page request happens again this tab does not exist and, well errors and problems ensue.

So, to fix this problem you need to recreate your tabs in your Page Init event so that they exist at the time when the Page's ViewState is loaded (especially if your Tabs cause a postback to the server or else you'll lose the event data associated with the tab change ...so your server-side tab index changed event will never occur).

I'm not sure if any of this is making sense so I'll try to explain this in some example code.

Here is the ASPX Page markup...it contains a button called "addTab" which, when clicked, will dynamically add a new TabPanel to the TabContainer (which is also on the page). The page also has a Label on it "currentTabIndex" which will display the ActiveTab's ID when it is selected. The Label's text is set when the TabContainer posts back to the server when the ActiveTabChanged event occurs:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" 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="smanager" runat="server"></asp:ScriptManager>
        <asp:Button ID="addTab" Text="Add Tab" onclick="addTab_Click" runat="server"/>
        <cc1:TabContainer ID="TabContainerContent" runat="server"  Height="150px" BackColor="White"  AutoPostBack="True">
        </cc1:TabContainer>  
        <asp:Label ID="currentTabIndex" runat="server"></asp:Label>
    </div>
    </form>
</body>
</html>


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:
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;
  }
}


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:

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){
      Session["dynamicTabIDs"] = dynamicTabIDs;
    }
  }
}


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.

Hopefully you understand what I'm getting at here.

Back to the code, in the Page Init event retrieve the tab-IDs-container...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):

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;
    }
  
  }
}


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:
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);
    }

  }

}


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 "currentTabIndex" label's text to the Tab ID of the active tab:

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
      currentTabIndex.Text=TabContainerContent.ActiveTab.ID;
    }

  }
}


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....

I tried that when I first started to answer this question, but 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;

-Frinny

This post has been edited by Frinavale: 18 June 2010 - 10:13 AM

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1