ASP.NET has been missing a good, free tab control for a long time. With the ACT Tab Container, we were finally given one. It typically runs in client-side only mode, but can interact with server-code if we set its AutoPostback property to true.
Compared to what we had before, it is a huge improvement. The peculiar thing about it, however, is that it isn’t actually an Ajax control. It doesn’t use asynchronous postbacks or web service calls to talk to the server — instead you just have these two mode: run it using client script only, or run it using server-side events and code-behind only.
So a few months ago I rectified this for a project, and only found out afterwards that Matt Berseth had already outlined the technique on his blog. You basically run the tab container in client-side mode, and add update panels to the tab panels that you want to be ajaxy. You then hook up the client-side ActivePageChanged event in such a way that it spoofs the Update Panel contained in the tab, causing an asynchronous (or partial) postback.
Matt also gave this technique a cool name. He called it ‘lazy loading the tab panel’. Like lazy loading in OOP, using this technique the update panels inside each tab panel only do something when its tab is selected. Information is loaded only when its needed, and not before.
I must admit that I hold some resentment against Matt for coming up with this first, and for coming up with the cool moniker for it. On the other hand, the solution I came up with encapsulates all of the javascript needed for this into a nice simple extender control that you can drop on your page, which his does not, and I’m rather proud of this.
The VS 2008 project for this extender is linked at the top of this post. To use it, you need to compile the project and add the compiled assembly to your project, or else just add the project to your solution and add a project reference.
1. Drop the TabContainerExtender control into your page.
2. Set the Extender’s TargetControlID property to your TabContainer’s ID.
3. In the RegisterUpdatePanels element of the Extender, map your tabs to your update panels. This mapping tells the extender which Update Panels to activate when each tab is selected.
Your markup will look something like this:
<cc2:TabContainerExtender ID="TabContainerExtender1" runat="server" TargetControlID="TabContainer1" OnActiveTabChanged="ActiveTabChanged"> <RegisterUpdatePanels> <cc2:UpdatePanelInfo TabIndex="0" UpdatePanelID="UpdatePanel1" /> <cc2:UpdatePanelInfo TabIndex="1" UpdatePanelID="UpdatePanel2" /> <cc2:UpdatePanelInfo TabIndex="2" UpdatePanelID="UpdatePanel3" /> </RegisterUpdatePanels> </cc2:TabContainerExtender>
4. If you want to add some code-behind to your active tab changed event, add set the OnActiveTabChanged property of the Extender to the name of your handler. The thrown event will pass the correct Index number for the active Tab, as well as the ID of the mapped Update Panel. The handler’s signature looks like this:
protected void ActiveTabChanged(int index, string panelID)
{
…
}
I highly encourage you to read Matt Berseth’s blog entry (which I have to admit is pretty good) to get a clear idea of the techniques being applied in this ajax extender. If you just need a quick solution, however, feel free to download this code from the link at the top and use it any way you like with no strings attached. There is a sample project attached to the solution that will demonstrate how to use the Tab Container Extender, in case you run into any problems with lazy loading your panels.
For reference, here is the code for the sample implementation, which loads controls on the fly based on the tab selected:
<cc1:TabContainer ID="TabContainer1" runat="server"> <cc1:TabPanel ID="TabPanel1" runat="server" HeaderText="Tab Panel 1"> <ContentTemplate> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> Content 1 ... <br /> <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder> </ContentTemplate> </asp:UpdatePanel> </ContentTemplate> </cc1:TabPanel> <cc1:TabPanel ID="TabPanel2" runat="server" HeaderText="Tab Panel 2"> <ContentTemplate> <asp:UpdatePanel ID="UpdatePanel2" runat="server"> <ContentTemplate> Content 2 ... <br /> <asp:PlaceHolder ID="PlaceHolder2" runat="server"></asp:PlaceHolder> </ContentTemplate> </asp:UpdatePanel> </ContentTemplate> </cc1:TabPanel> <cc1:TabPanel ID="TabPanel3" runat="server" HeaderText="Tab Panel 3"> <ContentTemplate> <asp:UpdatePanel ID="UpdatePanel3" runat="server"> <ContentTemplate> Content 3 ... <br /> <asp:PlaceHolder ID="PlaceHolder3" runat="server"></asp:PlaceHolder> </ContentTemplate> </asp:UpdatePanel> </ContentTemplate> </cc1:TabPanel> </cc1:TabContainer> <cc2:TabContainerExtender ID="TabContainerExtender1" runat="server" TargetControlID="TabContainer1" OnActiveTabChanged="ActiveTabChanged"> <RegisterUpdatePanels> <cc2:UpdatePanelInfo TabIndex="0" UpdatePanelID="UpdatePanel1" /> <cc2:UpdatePanelInfo TabIndex="1" UpdatePanelID="UpdatePanel2" /> <cc2:UpdatePanelInfo TabIndex="2" UpdatePanelID="UpdatePanel3" /> </RegisterUpdatePanels> </cc2:TabContainerExtender>
Hi,
I am having a problem with the Tabs control and the ValidatorCallout control and it would be great if you can give me some help.
I have 3 tabs, in each tab I have 3 textbox and a dropdown control, I have a validator for each one of them.
The submit button is outside of the Tabs control so when i click the submit button if the textbox controls on the second tab have not being filled then it does not set the focus to that second tab and show the validator callout, the same for the third tab and so on…
Can you help please?
Thanks a lot in advance
Hello James,
Thanks for posting such a useful implementation of Lazy Loading.
Couple of days back I downloaded the code and found that the code uses some special features of .Net 3.5 Framework, like Linq and DataContractJSONSerialization etc.
I’m using the Framework 2.0 of .Net and had modified the code accordingly. I thought it would be useful to share the changes with you so I’m sharing the same.
I modified the SerializeUpdatePanelInfoCollection method as follows:
Also in OnLoad method I replaced Linq code with normal iterative search in List.
Thanks Again,
Sudev Gandhi
Hi,
Sudev, I was wondering if you could please post the 2.0 version of the OnLoad method as well. I’m having trouble understanding the linq bits of code. Thanks a lot in advance. And thanks for sharing this with us James!
Rhea
Sudev,
I’m really glad you were able to get this working in 2.0. It’s a neat implementation. Well done.
Do you have any <strong><a href="http://www.cheapwindows7key.com/windows-7-key/windows-7-64-bit-key/cheap-windows-7-ultimate-64-bit-key.html" title="Windows 7 Ultimate">Windows 7 Ultimate</a></strong> other similar blogs related fields of expression. This information <strong><a href="http://www.cheapwindows7key.com/windows-7-key/windows-7-64-bit-key/cheap-windows-7-ultimate-64-bit-key.html" title="Windows 7 Ultimate Key">Windows 7 Ultimate Key</a></strong> has caused in me some quasi-cascade effect <strong><a href="http://www.cheapwindows7key.com/windows-7-key/windows-7-64-bit-key/cheap-windows-7-home-premium-64-bit-key.html" title="Windows 7 Home Premium">Windows 7 Home Premium</a></strong> that has resulted in a great rearangement of my knowledge almost akin to a complete <strong><a href="http://www.cheapwindows7key.com/windows-7-key/windows-7-64-bit-key/cheap-windows-7-professional-64-bit-key.html" title="Windows 7 Professional">Windows 7 Professional</a></strong> paradigm shift in the way I perceive the world. Thank you so <strong><a href="http://www.cheapwindows7key.com/office-2010-key" title="Office 2010">Office 2010</a></strong> much for this and I bet you wil accumulate a ton of Karma and positive chi due to <strong><a href="http://www.cheapwindows7key.com/office-2010-key" title="Microsoft Office 2010">Microsoft Office 2010</a></strong> your wonderful undertaking in this blog!
Can share this article is really happy, learn a lot of things and improve together
<a href="http://www.p90xworkoutus.com">P90x Workout</a>
<a href="http://www.p90xworkoutus.com">P90x Dvd</a>
Could anyone please post the source code for this? The Download Source Code link is not working.