Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Maintaining the ActiveTabIndex of the AJAX Control Toolkit TabContainer

1.00/5 (2 votes)
16 Apr 2008CPOL2 min read 1   353  
Restores the user's previously selected tab panel when they return to a page.

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:

VB
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:

VB
' 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:

VB
        ' 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:

VB
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)