Click here to Skip to main content
Click here to Skip to main content

Maintaining the ActiveTabIndex of the AJAX Control Toolkit TabContainer

By , 16 Apr 2008
 

Introduction

The TabContainer control in the AJAX Control Toolkit is a great way of displaying a lot of data in a very limited space on your web page. However, one problem with it is that when the user leaves the page and returns, it defaults back to the first tab - causing, in the best scenario, an extra mouse click, and in the worst-scenario, a confused or angry user (trust me, they're out there).

This article refers to and is, in fact, partly embedded in another article I wrote on maintaining the state of controls between visits to a page. If you haven't read it, I suggest you do so.

Using the code

One of the main reasons we can't easily maintain the clicked state of a tab is, in fact, one of the benefits of the tab control - switching between tabs doesn't cause a post back. However, in order to maintain any kind of state, at some point, we need to communicate back to our server, and this is the essence of my approach below. (Actually, does anybody know any client-side only methods for maintaining state? Managing cookies within JavaScript, for instance?)

The OnActiveTabChanged() event

[Aside: this section deals with JavaScript code, but because I have encapsulated everything in re-usable classes, the code examples below use VB.NET to render the JavaScript to the page. It is slightly harder to follow, but all part of the bigger project in the end.]

As the name implies, this property of the TabContainer() control allows you to specify the JavaScript code to call when the user switches between tabs:

If C.GetType Is GetType(AjaxControlToolkit.TabContainer) Then
    ' If there are multiple tab containers on this page,
    ' then we need a seperate proxy function for each
    Dim JS As New StringBuilder(vbCrLf)
    JS.Append("function SaveTabState_" & C.ID & "(){")
    JS.Append(vbCrLf & "_SaveTabState('" & C.ClientID & "','" & C.UniqueID & "');")
    JS.Append(vbCrLf & "}")
    Page.ClientScript.RegisterClientScriptBlock(Me.GetType, _
         "SaveTabState_" & C.ID, JS.ToString, True)

    ' Create the attribute to call this function
    DirectCast(C, AjaxControlToolkit.TabContainer).OnClientActiveTabChanged = _
                                             "SaveTabState_" & C.ID

Within that function, what we do is create a callback to the server using a standard web service call from JavaScript:

' Create common function. The routine before calls this
If Not HasRegisteredCommon Then
    JS = New StringBuilder(vbCrLf)
    JS.Append("function _SaveTabState(clientID, uniqueID){")
    JS.Append(vbCrLf & "var tabBehavior = $get(clientID).control;")
    JS.Append(vbCrLf & "var index = tabBehavior.get_activeTabIndex();")

    ' This web service reference must already have been
    ' setup by the developer in the script manager
    JS.Append(vbCrLf & "LookupService.SaveTabIndex('" & _
              Me.Page.Request.Path & "_' + uniqueID,index);")
    JS.Append(vbCrLf & "}")
    Page.ClientScript.RegisterClientScriptBlock(Me.GetType, _
                 "SaveTabState", JS.ToString, True)

And of course, with the new Microsoft AJAX Extensions framework, putting all this together is very simple using the ScriptManager() class. Below, we hook into the existing ScriptManager using the ScriptManagerProxy() class:

        ' Add the web service reference to the script manager
        Dim SMP As New ScriptManagerProxy()
        SMP.Services.Add(New ServiceReference("~/Services/LookupService.asmx"))
        Page.Controls.Add(SMP)
        HasRegisteredCommon = True
    End If
End If

The Lookup Web Service

The web service called in JavaScript is extremely simple:

Public Sub SaveTabIndex(ByVal UniqueTabID As String, ByVal Index As Integer)
        ' Simply save to the session
        System.Web.HttpContext.Current.Session(UniqueTabID) = Index
End Sub

Restoring state

We now have the current tab index stored in a session, which we can later access from the server - namely, when we are re-instantiating the page upon return. Simple, huh? If you are happy with that, it is just a case of setting TabContainer.ActiveTabIndex = CInt(Session(UniqueTabID)) in the Page.Load() event of your page.

However, we programmers like things tidy and lazy, so I have worked out a solution which means you don't even have to do that. See my other article on maintaining control state upon page revisits, for more information.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ben Liebert
Architect BlackBall Software
New Zealand New Zealand
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionSomething close - but probably not involving state...memberjonefer11 May '08 - 13:08 
GeneralRe: Something close - but probably not involving state...memberBen Liebert11 May '08 - 15:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 16 Apr 2008
Article Copyright 2008 by Ben Liebert
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid