Wednesday, March 21, 2012

TabContainer not maintaining ActiveTabIndex between postbacks

In the documentation online it said that the most recently selected tab should remain selected between postbacks. However, this does not seem to be happening for me; the first tab becomes the active tab every time I do a postback. Does anybody have any idea why this could be happening? The control that I am using to cause the postback is in the ContentTemplate of one of the TabPanel controls. Any help would be appreciated.

Hi,

I think you need to give some more specific information, without knowing that, it's hard to tell why since we can't reproduce the issue.

Can you show a simple repro?


Hi! The same is true for me. Let's say you have a TabContainer with 3 tabs. You've selected the third one and cause a postback, eg. by pressing F5. Try it out on the live demo of the Ajax Toolkit. I am trying to workaround by saving the selected one to the Session and reactivating it on the ActiveTabChanged Event of the TabContainer. This works out great for Tab2 to Tabx but let's say if you switch from Tab3 to Tab1 the value is written to the Session, but the ActiveTabChanged Event does not fire if you switch to the first Tab! What can I do to make the first tab stay selected or why does the change from Tab2, Tab3, Tabx to Tab1 doesn't fire a ActiveTabChanged Event?

Best regards...


maiklb99:

eg. by pressing F5.

Pressing F5 incurs a GETrequest, thus the state of current page won't be sent. So I think it's normal to lose the selectedIndex, unless you saved it on server side explicitly( e.g.: your solution of using Session ).


Hi!

a button click event on the page causes the same problem. The activetabchanged event is not fired when switching to tab1.

Sincerely, maiklb99


I have been unable to create a simple example that reproduces this problem, but I want to mention something else I just noticed. The ActiveTabChanged event is not being triggered when I do a postback. This implies to me that somehow the variable used to keep track of the ActiveTab is getting reset. I don't know where yet, because I do not explicitly assign a value to the ActiveTabIndex at any point in my code, but I thought this was a noteworthy point, since it may hep determine when the value is being reset.


But I can see the ActivedTabChanged event is fired. Here is a sample page:

<%@. Page Language="C#" %
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
<script runat="server"
protected void TabContainer1_ActiveTabChanged(object sender, EventArgs e)
{
Response.Write("changed fired");
}
</script
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>

</div>
<ajaxToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="2" OnActiveTabChanged="TabContainer1_ActiveTabChanged">
<ajaxToolkit:TabPanel ID="TabPanel1" runat="server" HeaderText="TabPanel1">
<ContentTemplate>
tab1
</ContentTemplate>
</ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel ID="TabPanel2" runat="server" HeaderText="TabPanel2">
<ContentTemplate>
tab2
</ContentTemplate>
</ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel ID="TabPanel3" runat="server" HeaderText="TabPanel3">
<ContentTemplate>
tab3
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
<asp:Button ID="Button1" runat="server" Text="Click me to postback" />
</form>
</body>
</html


I don't know the exact reason, but the event does not fire in my environment. Eventually this is caused by the fact, that I am using the control in an ASCX Control in a Sharepoint 2007 Webpart. My source is almost the same as yours but I am not initializing the ActiveTabIndex.


I have tried writing a simple test page to see if it works when it is little other than the TabContainer & TabPanels, and it did maintain the ActiveTabIndex then. What I am trying to figure out is what in my original code could possibly be causing the ActiveTabIndex to not be maintained. Since I do not assign values to any properties of the TabContainer anywhere other than the declaration in the *.aspx file, I am clueless as to where to look. I would say I thought that some other JavaScript code was interfering with the JavaScript code that keeps track of and returns the selected tab, but I haven't directly added any JavaScript to my application, so if there is any interference, I would not know where to look to find it. If somebody is willing to look at my complete code, let me know, because I don't know what I can post here that could help other than random bits of code that I have no reason to think are relavant to the problem.


My suggestion is try to strip items/features off the page one by one, then you may find out what is the cause.


Raymond, I just came across this same problem. I've created a small example for you. When I select a row from the GridView on "TabPanel2", the ActiveTabIndex is not maintained and appears to be reset. Any ideas?

ASPX

<%@. page autoeventwireup="true" codefile="Tabs.aspx.cs" inherits="Tabs" language="C#"title="Untitled Page" %><!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"><aspx:scriptmanager id="ScriptManager1" runat="server"></aspx:scriptmanager><ajax:tabcontainer id="TabContainer1" runat="server"><ajax:tabpanel id="TabPanel1" runat="server" headertext="TabPanel1"><contenttemplate>TabPanel1</contenttemplate></ajax:tabpanel><ajax:tabpanel id="TabPanel2" runat="server" headertext="TabPanel2"><contenttemplate>TabPanel2<asp:gridview id="GridView1" runat="server" autogenerateselectbutton="true"></asp:gridview></contenttemplate></ajax:tabpanel></ajax:tabcontainer></form></body></html>

CODE-BEHIND

using System;using System.Collections.Generic;public partialclass Tabs : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e) {if (!this.IsPostBack){List<int> numbers =new List<int>();for (int i = 1; i < 11; i++){numbers.Add(i);}GridView1.DataSource = numbers;GridView1.DataBind();} }}

A temporary fix, is to wrap the page contents within an UpdatePanel. This appears to keep the ActiveTabIndex. Is this the only way?


Even though I did not use a GridView in my application, I did use DataLists. I am wondering if the fact that these are both data controls has anything to do with it. When I attempted to write a sample application to demonstrate the problem, I used nothing other than simple Labels, TextBoxes, and Buttons (I obviously had to create some way to cause a postback from each tab). This did maintain the ActiveTabIndex. After reading your posting, I tried writing one with a DataList involved. Ironically, the one with the DataList maintained the ActiveTabIndex as well. I am still trying to figure out what it is that I do differently in my application. My DataLists are in *.ascx files, but that shouldn't make any difference, right? Here is my code:

ASPX File:

<%@. Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb"Inherits="AJAXEnabledWebApplication1._Default" %><%@. RegisterAssembly="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>DataList in TabContainer Test</title></head><body><form id="form1" runat="server"><asp:ScriptManager ID="ScriptManager1" runat="server"/><cc1:TabContainer ID="TabContainer1" runat="server"><cc1:TabPanel ID="TabPanel1" runat="server" HeaderText="TabPanel1"><ContentTemplate><asp:Button ID="Button1" runat="server" Text="Button"/></ContentTemplate></cc1:TabPanel><cc1:TabPanel ID="TabPanel2" runat="server" HeaderText="TabPanel2"><ContentTemplate><asp:DataList ID="DataList1" runat="server"><ItemTemplate><asp:Button ID="Button2" runat="server" CommandName="select" /></ItemTemplate></asp:DataList></ContentTemplate></cc1:TabPanel><cc1:TabPanel ID="TabPanel3" runat="server" HeaderText="TabPanel3"><ContentTemplate><asp:Button ID="Button3" runat="server" Text="Button"/></ContentTemplate></cc1:TabPanel></cc1:TabContainer></form></body></html>

CodeBehind (ASPX.VB) File:

Imports System.Data.SqlClientPartialPublic Class _Default :Inherits System.Web.UI.PageProtected Sub Page_Load(ByVal senderAs Object,ByVal eAs System.EventArgs)Handles Me.LoadIf Not IsPostBackThenDim categoriestableAs New DataTableDim categoriesadapterAs New SqlDataAdapter("SELECT name FROM categories", System.Configuration.ConfigurationManager.AppSettings("connectionstring"))categoriesadapter.Fill(categoriestable)Me.DataList1.DataSource = categoriestableMe.DataList1.DataBind()End IfEnd SubEnd Class

ecbruck:

Raymond, I just came across this same problem. I've created a small example for you. When I select a row from the GridView on "TabPanel2", the ActiveTabIndex is not maintained and appears to be reset. Any ideas?

ASPX

<%@. page autoeventwireup="true" codefile="Tabs.aspx.cs" inherits="Tabs" language="C#"title="Untitled Page" %><!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"><aspx:scriptmanager id="ScriptManager1" runat="server"></aspx:scriptmanager><ajax:tabcontainer id="TabContainer1" runat="server"><ajax:tabpanel id="TabPanel1" runat="server" headertext="TabPanel1"><contenttemplate>TabPanel1</contenttemplate></ajax:tabpanel><ajax:tabpanel id="TabPanel2" runat="server" headertext="TabPanel2"><contenttemplate>TabPanel2<asp:gridview id="GridView1" runat="server" autogenerateselectbutton="true"></asp:gridview></contenttemplate></ajax:tabpanel></ajax:tabcontainer></form></body></html>

CODE-BEHIND

using System;using System.Collections.Generic;public partialclass Tabs : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e) {if (!this.IsPostBack){List<int> numbers =new List<int>();for (int i = 1; i < 11; i++){numbers.Add(i);}GridView1.DataSource = numbers;GridView1.DataBind();} }}


Hi,

I looked into it. It seems it's caused by not saving client state correctly when the postback is triggered by GridView. My solution is saving it manually.

<%@. Page Language="C#" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
<script runat="server"
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
System.Collections.Generic.List<int> numbers = new System.Collections.Generic.List<int>();

for (int i = 1; i < 11; i++)
{
numbers.Add(i);
}

GridView1.DataSource = numbers;
GridView1.DataBind();
}
}
</script
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
function OnChanged(sender, args)
{
sender.get_clientStateField().value = sender.saveClientState();
}
</script>

</head>
<body>
<form id="form1" runat="server">
<asp:scriptmanager id="ScriptManager1" runat="server">
</asp:scriptmanager>
<ajaxtoolkit:tabcontainer OnClientActiveTabChanged="OnChanged"id="TabContainer1" runat="server" ActiveTabIndex="0">
<ajaxtoolkit:tabpanel id="TabPanel1" runat="server" headertext="TabPanel1">
<contenttemplate>
TabPanel1
</contenttemplate>
</ajaxtoolkit:tabpanel>
<ajaxtoolkit:tabpanel id="TabPanel2" runat="server" headertext="TabPanel2">
<contenttemplate>
TabPanel2<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:gridview id="GridView1" runat="server" autogenerateselectbutton="True">
</asp:gridview>
</contenttemplate>
</ajaxtoolkit:tabpanel>
</ajaxtoolkit:tabcontainer>
</form>
</body>
</html>


Though my above workaround may work, but I don't think it should be necessary.

So I created an item in codeplex to track this.

http://www.codeplex.com/AtlasControlToolkit/WorkItem/View.aspx?WorkItemId=12838

No comments:

Post a Comment