Wednesday, March 28, 2012

tab container and tab panels

I'm getting what I think is odd behavior from the tab panels. Everything of course works fine if the tab panels are static. However, I want to programmatically add to the tab container in my code behind.

The first time the page loads the outline of the tab container is present (which is fine). I click a button and do a postback for the update panel and two tabpanels are added to the tabcontainer. If I do another postback, then I get an error "There is no source code available for the current location." message box. I click OK. I then get a message box that says, "ArgumentOutOfRangeException was unhandled by user code ....Specified argument was out of range of valid values...Parameter name: index".

For example,

"UpdatePanel1" runat="server" UpdateMode="Conditional"> "TabContainer1" runat="server"> "HiddenField1" runat="server" OnValueChanged="HandleNodeClick"/>public void HandleNodeClick(Object sender, EventArgs e){ AjaxControlToolkit.TabPanel panel1 =new AjaxControlToolkit.TabPanel(); panel1.HeaderText ="panel1"; panel1.Visible =true; panel1.ID ="panel1"; AjaxControlToolkit.TabPanel panel2=new AjaxControlToolkit.TabPanel(); panel2.HeaderText ="panel2"; panel2.Visible =true; panel2.ID ="panel2"; TabContainer1.Controls.Add(panel1); TabContainer1.Controls.Add(panel2);}
As a workaround I tried the following, which didn't work either. I have three different formats of tabcontainers I want to use. I tried just putting the three different tabcontainers on the aspx page to begin with. In the code behind, on page load I set .visible=false for all 3 (which worked as expected). Based on an event, I then set .visible=true for a given tabcontainer. However, only the text of the desired tabcontainer is displayed -- the formatting, the panels, etc. aren't. Suggestions for either of these approaches is much appreciated.

In my case I have successfully created the tabs and the buttons on them - they display just fine and the tabs select. However, as soon as I click on any of the buttons the same error arises. Setting an eventhandler for each button does not cure the problem.

I am very keen for a quick solution!


Further investigation shows that the problem does not even relate to adding controls to the tab but arising even if adding tabs dynamically.

I added a button outside the tab and then just did the tab adding.:

Dim FC()As cCategory = cCategory.AllCats
Dim iAsInteger
For i = 0 To FC.length-1
Dim tab As New AjaxControlToolkit.TabPanel
tab.HeaderText = FC(i).TabName
tab.ID = "tab" & CStr(i)
tbForms.Tabs.Add(tab)
NexttbForms.ActiveTabIndex = 0

A click on the static button then produces the error message.

It seems as if the wiring up of the postback info is incomplete with the dynamically created tabs.


OK guys - I found most of the answer from another thread - use Page_Init

However . . .

ProtectedSub Page_Init(ByVal senderAsObject,ByVal eAs System.EventArgs)HandlesMe.InitDim FC()As cCategory = cCategory.AllCats
Dim iAsInteger
For i = 0To 0
Dim tabAsNew AjaxControlToolkit.TabPanel
tab.HeaderText = FC(i).TabName
tab.ID ="tab" &CStr(i)
Dim FM()As cForm = cForm.Tab(FC(i).TabId)
Dim FMname(FM.Length - 1)AsString
Dim jAsInteger
For j = 0To 0
Dim btnAsNew Button
btn.Text = FM(j).Description
btn.ID ="btn" &CStr(i) &":" &CStr(j)
AddHandler btn.Click,AddressOf ButtonClick
tab.Controls.Add(btn)
FMname(j) = FM(j).Description
Next
tbForms.Tabs.Add(tab)
Next
EndSub

PublicSub ButtonClick(ByVal senderAsObject,ByVal eAs System.EventArgs)
EndSub

This fires a postback OK but this never reaches the ButtonClick routine.

Why?


Making progress very slowly!

The Page_Init is performed every time a postback occurs (Before Page_Load) and at that time the dynamically added control do not exist (they have to be re-created each time around, it seems) If I test for postback at the start of Page_Init and do not do the dynamic creation at that time, then the same error as before occurs.

I do not fully understand what is going on but I guess that the postback cannot connect up with the event handling which was created the first time around. Presumably I need to find some way of working out what the postback actually is and look at it explicitly.

Any ideas, folks?


I think I'm hitting the same issue.

I've added two tab panels to my TabContainer statically. The tab panels host the ReportViewer control which is possibly a bit ambitious but it is a business requirement if possible.

Then in the Page_Load event handler I add a third tab panel dynamically with the following code block :

ReportViewer rv = new ReportViewer();
rv.ID = "rv3";
rv.ProcessingMode = ProcessingMode.Remote;
rv.Height = 500;
rv.Width = 950;
rv.Reset();
SetReportParameters(rv, 53); // this just inits the reportviewer

AjaxControlToolkit.TabPanel tabPanel = new AjaxControlToolkit.TabPanel();
tabPanel.ID = "tab3";
tabPanel.HeaderText = "Dynamically added tab panel";
tabPanel.Controls.Add(new LiteralControl("<ContentTemplate>"));
tabPanel.Controls.Add(rv);
tabPanel.Controls.Add(new LiteralControl("</ContentTemplate>"));
//this.tabReports.Controls.Add(tabPanel);
this.tabReports.Controls.AddAt(tabReports.Controls.Count, tabPanel);

This all works fine but it's not really dynamic yet. So I then add a button to the page outside of the TabContainer and in the event handler for it I use a similar code block to the above except I use a different TabPanel.ID. This is when I run into the problem. Before the button event handler code is entered I'm getting the ArgumentOutOfRangeException and VS dumps me into the TabPanelCollection.cs class in the TabPanel method.

public new TabPanel this[int index]
{
get { return (TabPanel)base[index]; }
}

In my case index=2 and the Exception tells me the it is out of range of valid values. What is confusing me is that my code to insert the new panel hasn't been run yet so something else must be going on. In order to speed up diagnostics on this I'm going to remove the ReportViewers and put in some simple controls but in the meantime it would be good if someone from the AJAX team could comment on this issue.

I've now got wroking code - but at the price of a fudge!

Firstly, the dynamic creation must be done in Page_Init (not Page_Load) and must be done on every Postback, not just frst time through.

Secondly, in Page_Load on Postback, I check the Page.Request.Form collection. Despite all that I have read, there is nothing in the first few entries but (4) there is the full name of the control and its text value.

Dim sAsString = Page.Request.Form.AllKeys(4)
If s.ToLower.StartsWith("tbforms")Then
Dim s1()AsString = s.Split("$")
Dim s2AsString = s1(1).Substring(3)
Dim s3AsString = s1(2).Substring(3)
Dim tabNoAsInteger =CInt(s2)
Dim btnNoAsInteger =CInt(s3)

I am far from happy with this as it depends on an undpecified magic number (which, as we all know, chnages just when you can least afford it!)

I still suspect that there is a bug lurking somewhere here.

No comments:

Post a Comment