Wednesday, March 28, 2012

Dynamic Ajax Tab Container raises unhandled exception: Specified argument was out of the r

Hi -

I've a problem with the ajax tab container: I try to add additional ajax tab panels dynamically at run time. This works fine, but as soon as I do it, any button I click on the page throws the exception below.

So, if I comment these 2 lines out:

Dim tpAsNew AjaxControlToolkit.TabPanel

Me.TCSpecialties.Tabs.Add(tp)

everything works fine (TCSpecialties is a Tab Container). Once I leave them in, this exception is thrown:

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

Description:An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details:System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: value

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.


Stack Trace:

[ArgumentOutOfRangeException: Specified argument was out of the range of valid values.Parameter name: value] AjaxControlToolkit.TabContainer.set_ActiveTabIndex(Int32 value) +381 AjaxControlToolkit.TabContainer.LoadClientState(String clientState) +160 AjaxControlToolkit.ScriptControlBase.LoadPostData(String postDataKey, NameValueCollection postCollection) +73 AjaxControlToolkit.TabContainer.LoadPostData(String postDataKey, NameValueCollection postCollection) +32 AjaxControlToolkit.ScriptControlBase.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection) +11 System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +718 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3776

Does anyone have a clue as to what may be going on??

Any help highly appreciated

I think you need to set the activetab which is null

somthing like TCSpecialties.ActiveTab = tp

This will set the active tab to the newly added tab.


I did that - still the same behavior as before. The tabs get displayed correctly, as a matter of fact. Any ideas?


By "adding tabs dynamically at runtime" are you doing this client side or server side? Can you file a bug at codeplex at attach a simple repro?


I am doing this on the server side ... what I meant is that the controls are not dropped in the form at designtime but rather created based on database fields (one Tab per record, with 3 records in the database). Will try to create a repro


You may need to recreate the tab panels when the postback occurs in the Page_init because the tabpanels do not exist on post backs until they have been made...

So in Page_init you should call a function that makes the default tab collection and then later on the page you can add a new tab panel to the collection.

Hope this makes sense.


That fixed itSmile

Thanks very much!!!!

Oliver


Thanks guys for the thread. It has saved us HEAPS of time.

After reading it though I still had a few problems getting it to work (which it is now).
These are probably pretty obvious to most of you out there, but it may be helpful for those reading this thread that still can't get it working.

We are now creating the tabbed panels dynamically in Page_Init as instructed.
One thing we did wrong was to only do this if it was not a postback. In hindsight we obviously we needed to do this all the time.

Also for those who are wondering how to save the selected values on the page if you are recreating the tab panels everytime, I think that the save view state and load view state events are doing this for you automatically; I think they just need to have the controls created (which you are now doing in page_init) and then they will do the rest.

Isn't life grand :)

Thanks again for sharing this info with everyone.

Mark


Can you please post a code example here of what must be written inside the page_init function ?


Just create whatever dynamic controls you have. If you add a text box with the ID="tb1" dynamically (I know, it's more likely you created something data driven), just add the following

dim l as new textbox

l.id="tb1"

me.page.controls.add(l)

That's it. Just do this for any controls you added. Note: Do not reset the values, viewstate will take care of that for you.

Now, you can simply access the text property somewhere else in your code behind as

l.text

and it will have the text the user entered. Hope that helps


Hello,

I am doing it according to this post but still getting "Index out of range" exception when I try to add a second TabPanel by clicking a button...

Any ideas?...

public partial class TestPage : System.Web.UI.Page
{
private TabContainer _tabContainer;

protected void Page_Init(object sender, EventArgs e)
{
_tabContainer = new TabContainer();
_tabContainer.Height = Unit.Pixel(250);

TabPanel tab = new TabPanel();
tab.HeaderText = "New Tab 1";

_tabContainer.Tabs.Add(tab);

tab = new TabPanel();
tab.HeaderText = "New Tab 2";

_tabContainer.Tabs.Add(tab);
_tabContainer.ActiveTab = tab;

ContainerPanel.Controls.Add(_tabContainer);
}
protected void Button1_AddTab(object sender, EventArgs e)
{
TabPanel tab = new TabPanel();
tab.HeaderText = "New Tab 3";

_tabContainer.Tabs.Add(tab);
_tabContainer.ActiveTab = tab;
}
}


Hey can you clarify the sentence:

"

So in Page_init you should call a function that makes the default tab collection and then later on the page you can add a new tab panel to the collection."

What's a default tab collection? I'm having the same problem and I don't really understand the solution.

Thanks


I can't really clarify better than I did before... Just look at the code I posted and you'll understand...

Thanks,

David


Can some please explain what is the reason behind this error?

Is it a feature or a bug?

I thank all for the answers, but eventually they either unclear or imply that if I want to add tabs dynamically then I have to create all the other controls on page dynamically (which seems to me somehow unpractical if I have a control rich page).

Any ideas?


This is what I found as a solution to this mess.

Assume you have a TabContainer with a TabPanel at design time. You also have a button which when clicked adds a new TabPanel to the TabContainer at runtime.

On postback, every TabPanel already added dynamically must be recreated before the Button_Click and the Page_Load are processed. In other words, this applies to all TabPanels except for the first one. This can be done in the Page_Init handler which I do not recommend for a very good reason: As soon as you mess with it you have to recreateall other dynamic controls your page may contain!

On the other hand, the TabContainer control has an Init handler itself so why not use it insteadWink

The following example adds a new TabPanel every time the button is clicked. Each tab has a header "Tab X" where X = 1 ... tabIndexName. You also need the tabIndexName static member to keep count of how many TabPanels have been created so far. Last but not least, have in mind that you cannot use the ViewState object inside the Init method.

public partialclass TabContainerTest : System.Web.UI.Page
{
public static int tabIndexName;

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
tabIndexName = 2;
}
}

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

protected void TabContainer1_Init(object sender, EventArgs e)
{
if (IsPostBack)
{
for (int i = 1; i < tabIndexName - 1; i++)
{
AjaxControlToolkit.TabPanel tab =new AjaxControlToolkit.TabPanel();
tab.HeaderText ="Tab " + Convert.ToString(i + 1);
TabContainer1.Tabs.Add(tab);
}
}
}
}

Hope this helps.

No comments:

Post a Comment