Hi Richard,
This issue, as I said, is due to the sequence of the execution of the code.
I'll try to rephrase.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.Page.RegisterRequiresControlState(this);
this._initialized = true;
if (this._cachedActiveTabIndex > -1)
{
this.ActiveTabIndex = this._cachedActiveTabIndex;
}
else if (this.Tabs.Count > 0)
{
this.ActiveTabIndex = 0;
}
}
Please pay attention to following code:
else if (this.Tabs.Count > 0)
{
this.ActiveTabIndex = 0;
}
It means if there's no tab added in the TabContainer this.ActiveTabIndex=0
will not be executed. It's reasonable. However, the Init of the Controls
that are added in the aspx fires earlier than the Page's Init. So the
result is, the TabContainer's ActiveTabIndex is -1 (it's default value that
is set in its constructor method). Then the code to add the TabPanels fires
(but it DOES NOT change the ActiveTabIndex of TabContainer). On the render
stage, the TabPanel checks the ActiveTabIndex. Since it's now -1 the
TabPanel assumes there's no active tab and it hides all the tabs at client
side.
So, to solve this issue, we have two options, obviously:
1. As I mentioned, add the TabPanels on an earlier stage than the
TabContainer's Init. The Page's PreInit is probably a good choice.
2. Set the ActiveTabIndex manually after the TabPanel has been added
(following sample is for the code in your first post):
protected void Page_PreRender(object sender, EventArgs e)
{
this.tc2.ActiveTabIndex = 0; //Manually set the active tab index.
}
protected void Page_Init(object sender, EventArgs e)//Or just use
Page_PreInit so that we don't have to manually set the active tab index.
{
this.tc1.Tabs[0].Controls.Add(new LiteralControl("I can add content to an
existing panel"));
TabPanel panel = new TabPanel();
panel.HeaderText = "tab2";
panel.Controls.Add(new LiteralControl("I can even add a new panel to a
container which already has a panel"));
this.tc1.Tabs.Add(panel);
TabPanel[] newpanels = new TabPanel[3];
for (int iCnt = 0; iCnt < 3; iCnt++)
{
newpanels[iCnt] = new TabPanel();
newpanels[iCnt].HeaderText = String.Concat("New Panel" + iCnt);
newpanels[iCnt].Controls.Add(new LiteralControl("But I can't add new
panels"));
this.tc2.Tabs.Add(newpanels[iCnt]);
}
}
As to your current scenario I think you can use the second option because
you're using the usercontrol and it'll generally involve some page life
cycle issues if we choose the event incautiously.
I understand you want to learn more about the page life cycle. But I
haven't found any book that is targeted to this topic.
I would like to tell you how I learn the page life cycle myself. Basically
I have two options:
1. Use the Reflector:
http://www.red-gate.com/products/reflector/index.htm
This response contains a reference to a third party World Wide Web site.
Microsoft is providing this information as a convenience to you. Microsoft
does not control these sites and has not tested any software or information
found on these sites; therefore, Microsoft cannot make any representations
regarding the quality, safety, or suitability of any software or
information found there. There are inherent dangers in the use of any
software found on the Internet, and Microsoft cautions you to make sure
that you completely understand the risk before retrieving any software from
the Internet.
Open the reflector, find the Page class and it's method:
private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool
includeStagesAfterAsyncPoint)
Then you can go on your way to track the page life cycle.
2. Debug the ASP.NET source code:
http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to
-debug-net-framework-source-code.aspx
The advantage of this option is, we can set breakpoints.
In addition, there's a Page Life Cycle methods list in this documentation:
http://msdn.microsoft.com/en-us/library/ms379581(VS.80).aspx
Please have a try and let me know if you need further assistance. If it
still doesn't work please send a demo project to me. My email is
(e-mail address removed).
Regards,
Allen Chen
Microsoft Online Support
--------------------
| From: "RichB" <
[email protected]>
| References: <
[email protected]>
<
[email protected]>
| Subject: Re: Asp.Net AJAX dynamically added Tab Control not displaying
| Date: Thu, 9 Oct 2008 14:33:45 +0100
| Lines: 371
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2900.5512
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.5579
| X-RFC2646: Format=Flowed; Original
| Message-ID: <
[email protected]>
| Newsgroups: microsoft.public.dotnet.framework.aspnet
| NNTP-Posting-Host: 93-96-97-68.zone4.bethere.co.uk 93.96.97.68
| Path: TK2MSFTNGHUB02.phx.gbl!TK2MSFTNGP01.phx.gbl!TK2MSFTNGP02.phx.gbl
| Xref: TK2MSFTNGHUB02.phx.gbl
microsoft.public.dotnet.framework.aspnet:77591
| X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet
|
| Allen thanks again,
|
| I am slowly getting to grips with the lifecycle, but would never have
picked
| this up. I do actually have the source for the ajaxtoolkit, but if I had
| just downloaded the dlls then is trying each of the delegate methods for
the
| lifecycle the only way that I could have established this? or is the mere
| presence of the OnInit override an indication that content should be
added
| PreInit.
|
| I assume however that it is also true, some actions cannot be taken until
| after a lifecycle event has occured, though I would appreciate it if you
| could point me at some decumentation with examples which illustrates this
| point.
|
| My final aim is to add the control within the Accordion custom control
that
| you helped me with previously. I have tried to do this today, by
including a
| tab panel within the ContentUserControl. Although I have the Accordion
| control constructed at Page_PreInit within the aspx file, the Tabbed
Panels
| within the TabContainer within the CustomUserCOntrol are not being added.
|
| What is happening in this case? My code extracts are below.
|
| If you can recomend some documents/books which I can read around the
subject
| of page life cycle I would appreciate it. Although I think I understand
the
| stages of the lifecyle, I don't seem to have a full understanding of the
| lifecyle where custom/user controls are involved.
|
| Thanks,
| Richard
|
| ContentUserControl.ascx.cs
| <%@ Control Language="C#" AutoEventWireup="true"
|
| CodeFile="ContentUserControl.ascx.cs"
| Inherits="AccordionTest.ContentUserControl" %>
|
| <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit"
|
| TagPrefix="cc1" %>
|
|
|
| <cc1:TabContainer runat="server" ID = "tc1"><cc1:TabPanel
| HeaderText="0"><ContentTemplate>fist tab</ContentTemplate></cc1:TabPanel>
|
| <cc1:TabPanel HeaderText="1"><ContentTemplate>is the second
| tab</ContentTemplate> </cc1:TabPanel></cc1:TabContainer>
|
| <asp:Button ID="Button1" runat="server" Text="Button"
onload="Button1_Load"
|
| />
|
|
| Browser Source:
| <div id="Accordion1">
| <input type="hidden" name="Accordion1_AccordionExtender_ClientState"
| id="Accordion1_AccordionExtender_ClientState" /><div>
| <div style="background-color:Gray;">
| <span id="ctl07_ctl01_Label1">HeaderTest_96</span>
| </div>
| </div><div style="display:block;">
| <div class="ajax__tab_xp" id="ctl08_ctl00_tc1"
style="visibility:hidden;">
| <div id="ctl08_ctl00_tc1_header">
|
| </div><div id="ctl08_ctl00_tc1_body">
|
| </div>
| </div>
|
| <input type="submit" name="ctl08$ctl00$Button1" value="ContentTest_96"
| id="ctl08_ctl00_Button1" />
|
| </div>
|
| | > Hi Richard,
| >
| > Please try to use Page_PreInit instead of Page_Init.
| >
| > The OnInit of TabContainer fires earlier than the Page_Init. Thus, if we
| > add controls in the Page_Init the TabPanels will not be shown.
| >
| > Please have a look at the source code of the TabContainer control:
| > protected override void OnInit(EventArgs e)
| > {
| > base.OnInit(e);
| > this.Page.RegisterRequiresControlState(this);
| > this._initialized = true;
| > if (this._cachedActiveTabIndex > -1)
| > {
| > this.ActiveTabIndex = this._cachedActiveTabIndex;
| > }
| > else if (this.Tabs.Count > 0)
| > {
| > this.ActiveTabIndex = 0;
| > }
| > }
| >
| > We can see if there's no tabs added in the TabContainer the
ActiveTabIndex
| > will not be assigned 0. And The default value of the ActiveTabIndex is
-1.
| > On the render stage, TabContainer will check the ActiveTabIndex. If
| > it's -1
| > then definitely no tab will be shown.
| >
| > Please have a try and let me know if it works.
| > Regards,
| > Allen Chen
| > Microsoft Online Community Support
| >
| >
| > Delighting our customers is our #1 priority. We welcome your comments
and
| > suggestions about how we can improve the support we provide to you.
Please
| > feel free to let my manager know what you think of the level of service
| > provided. You can send feedback directly to my manager at:
| > (e-mail address removed).
| >
| > ==================================================
| > Get notification to my posts through email? Please refer to
| >
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
| >
| > Note: The MSDN Managed Newsgroup support offering is for non-urgent
issues
| > where an initial response from the community or a Microsoft Support
| > Engineer within 1 business day is acceptable. Please note that each
follow
| > up response may take approximately 2 business days as the support
| > professional working with you may need further investigation to reach
the
| > most efficient resolution. The offering is not appropriate for
situations
| > that require urgent, real-time or phone-based interactions or complex
| > project analysis and dump analysis issues. Issues of this nature are
best
| > handled working with a dedicated Microsoft Support Engineer by
contacting
| > Microsoft Customer Support Services (CSS) at
| >
http://support.microsoft.com/select/default.aspx?target=assistance&ln=en-us.
| > ==================================================
| > This posting is provided "AS IS" with no warranties, and confers no
| > rights.
| >
| > --------------------
| > | From: "RichB" <
[email protected]>
| > | Subject: Asp.Net AJAX dynamically added Tab Control not displaying
| > | Date: Tue, 7 Oct 2008 17:01:41 +0100
| > | Lines: 204
| > | X-Priority: 3
| > | X-MSMail-Priority: Normal
| > | X-Newsreader: Microsoft Outlook Express 6.00.2900.5512
| > | X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.5579
| > | X-RFC2646: Format=Flowed; Original
| > | Message-ID: <
[email protected]>
| > | Newsgroups: microsoft.public.dotnet.framework.aspnet
| > | NNTP-Posting-Host: 93-96-97-68.zone4.bethere.co.uk 93.96.97.68
| > | Path: TK2MSFTNGHUB02.phx.gbl!TK2MSFTNGP01.phx.gbl!TK2MSFTNGP06.phx.gbl
| > | Xref: TK2MSFTNGHUB02.phx.gbl
| > microsoft.public.dotnet.framework.aspnet:77457
| > | X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet
| > |
| > | I am trying to get to grips with the asp.net ajaxcontrol toolkit, and
am
| > | trying to add a tabbed control to the page.
| > |
| > | I have no problems within the aspx file, and can dynamically
manipulate
| > a
| > | tabcontainer which has 1 panel already, however I want to try create
the
| > | TabPanels dynamically. I followed the advice here:
| > |
| > |
http://www.asp.net/learn/ajax-videos/video-156.aspx (3rd comment - Joe
| > | Stagner)
| > |
| > | I am finding that the container is hidden.
| > |
| > | I have found that I can work around this by creating the first tab
| > within
| > | the aspx, then performing RemoveAt(0) to remove that tab when I've
added
| > the
| > | others. This works, but is not ideal as I can't add the original
| > container
| > | dynamically. Is there another way to do this, and what is the reason
for
| > | this behaviour?
| > |
| > |
| > | Thanks,
| > | Richard
| > |
| > |
| > | My code is as follows:
| > | aspx
| > | <%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs"
| > |
| > | Inherits="_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 id="Head1" runat="server">
| > |
| > | <title>Untitled Page</title>
| > |
| > | </head>
| > |
| > | <body>
| > |
| > | <form id="form1" runat="server">
| > |
| > | <div>
| > |
| > | <asp:ScriptManager ID="ScriptManager1" runat="server">
| > |
| > | </asp:ScriptManager>
| > |
| > |
| > |
| > |
| > | <cc1:TabContainer ID="tc1" runat="server" >
| > |
| > | <cc1:TabPanel runat="server" HeaderText="TabPanel1" ID="TabPanel1">
| > |
| > | <ContentTemplate>This is the content - </ContentTemplate>
| > |
| > | </cc1:TabPanel></cc1:TabContainer>
| > |
| > | </div>
| > |
| > |
| > |
| > | <div>
| > |
| > | <cc1:TabContainer ID="tc2" runat="server">
| > |
| > |
| > | </cc1:TabContainer>
| > |
| > | </div>
| > |
| > |
| > |
| > | </form>
| > |
| > | </body>
| > |
| > | </html>
| > |
| > |
| > |
| > | aspx.cs
| > |
| > | using System;
| > |
| > | using System.Configuration;
| > |
| > | using System.Data;
| > |
| > | using System.Linq;
| > |
| > | using System.Web;
| > |
| > | using System.Web.Security;
| > |
| > | using System.Web.UI;
| > |
| > | using System.Web.UI.HtmlControls;
| > |
| > | using System.Web.UI.WebControls;
| > |
| > | using System.Web.UI.WebControls.WebParts;
| > |
| > | using System.Xml.Linq;
| > |
| > | using AjaxControlToolkit;
| > |
| > | public partial class _Default : System.Web.UI.Page
| > |
| > | {
| > |
| > | protected void Page_Init(object sender, EventArgs e)
| > |
| > | {
| > |
| > | this.tc1.Tabs[0].Controls.Add(new LiteralControl("I can add content to
| > an
| > | existing panel"));
| > |
| > | TabPanel panel = new TabPanel();
| > |
| > | panel.HeaderText = "tab2";
| > |
| > | panel.Controls.Add(new LiteralControl("I can even add a new panel to a
| > | container which already has a panel"));
| > |
| > | this.tc1.Tabs.Add(panel);
| > |
| > | TabPanel[] newpanels = new TabPanel[3];
| > |
| > | for (int iCnt = 0; iCnt < 3; iCnt++)
| > |
| > | {
| > |
| > | newpanels[iCnt] = new TabPanel();
| > |
| > | newpanels[iCnt].HeaderText = String.Concat("New Panel" + iCnt);
| > |
| > | newpanels[iCnt].Controls.Add(new LiteralControl("But I can't add new
| > | panels"));
| > |
| > | this.tc2.Tabs.Add(newpanels[iCnt]);
| > |
| > | }
| > |
| > |
| > | }
| > |
| > |
| > |
| > |
| > | }
| > |
| > |
| > |
| > |
| > |
| > | The source of the resultant page is below(note that the dynamically
| > added
| > | tags are styled as "display:none; visibility:hidden"):
| > | <div class="ajax__tab_xp" id="tc1" style="visibility:hidden;">
| > | <div id="tc1_header">
| > | <span id="__tab_tc1_TabPanel1">TabPanel1</span><span
| > | id="__tab_tc1_ctl00">tab2</span>
| > | </div><div id="tc1_body">
| > | <div id="tc1_TabPanel1">
| > | This is the content - I can add content to an existing panel
| > | </div><div id="tc1_ctl00" style="display:none;visibility:hidden;">
| > | I can even add a new panel to a container which already has a panel
| > | </div>
| > | </div>
| > | </div>
| > | </div>
| > |
| > |
| > | <div>
| > | <div class="ajax__tab_xp" id="tc2" style="visibility:hidden;">
| > | <div id="tc2_header">
| > | <span id="__tab_tc2_ctl00">New Panel0</span><span
| > id="__tab_tc2_ctl01">New
| > | Panel1</span><span id="__tab_tc2_ctl02">New Panel2</span>
| > | </div><div id="tc2_body">
| > | <div id="tc2_ctl00" style="display:none;visibility:hidden;">
| > | But I can't add new panels
| > | </div><div id="tc2_ctl01" style="display:none;visibility:hidden;">
| > | But I can't add new panels
| > | </div><div id="tc2_ctl02" style="display:none;visibility:hidden;">
| > | But I can't add new panels
| > | </div>
| > | </div>
| > | </div>
| > | </div>
| > |
| > |
| > |
| > |
| > |
| > |
| >
|
|
|
|