Sunday, March 11, 2012

tabContainers OnActiveTabChanged fires twice

Hi,

It seems to be all right with what you posted.

It will be helpful for trouble shooting if you post full source of the page.


The aspx code:

<cc1:TabContainer ID="viewTabContainer" Height="425" Width="100%" runat="server" AutoPostBack="True" OnActiveTabChanged="viewTabContainer_ActiveTabChanged"> <cc1:TabPanel ID="persoonsTabPanel" runat="server"> <HeaderTemplate> <asp:Label ID="persoonsTabLabel" runat="server"></asp:Label></HeaderTemplate> <ContentTemplate>' Large table </ContentTemplate> </cc1:TabPanel> <cc1:TabPanel ID="relatiesTabPanel" runat="server"> <HeaderTemplate> <asp:Label ID="relatiesTabLabel" runat="server"></asp:Label></HeaderTemplate> <ContentTemplate> <table class="viewTable"> <tr> <td class="viewTableTD"> <asp:PlaceHolder ID="relatieViewPlaceHolder" runat="server" EnableViewState="false"> </asp:PlaceHolder> </td> <td class="viewTableTD"> <asp:PlaceHolder ID="relatieSelectPlaceHolder" runat="server" EnableViewState="false"> </asp:PlaceHolder> </td> </tr> </table> </ContentTemplate> </cc1:TabPanel> <cc1:TabPanel ID="financieelTabPanel" runat="server"> <HeaderTemplate> <asp:Label ID="financieelTabLabel" runat="server"></asp:Label></HeaderTemplate> <ContentTemplate>' Large table </ContentTemplate> </cc1:TabPanel> <cc1:TabPanel ID="optieTabPanel" runat="server"> <HeaderTemplate> <asp:Label ID="optieTabLabel" runat="server"></asp:Label></HeaderTemplate> <ContentTemplate> Optie </ContentTemplate> </cc1:TabPanel> <cc1:TabPanel ID="aTabPanel" runat="server"> <HeaderTemplate> <asp:Label ID="aTabLabel" runat="server"></asp:Label></HeaderTemplate> <ContentTemplate> Testing tab </ContentTemplate> </cc1:TabPanel></cc1:TabContainer>

The aspx.vb code:

PartialClass Beheer_Deelnemer_DeelnemerInherits System.Web.UI.PagePrivate dAs DeelnemerPrivate _wijzigingenAs Boolean Protected Sub Page_Load(ByVal senderAs Object,ByVal eAs System.EventArgs)Handles Me.Load d =New DeelnemerIf Not Page.IsPostBackThen getTaal() getView() checkView("all")End If End Sub Private Sub showAlert(ByVal typeAs String,Optional ByVal tekstAs String ="")Select Case typeCase"error" viewValidationSummary.Visible =True alertLabel.Visible =False alertPanel.Visible =True Case"alert" viewValidationSummary.Visible =False alertLabel.Text = tekst alertLabel.Visible =True alertPanel.Visible =True Case Else alertPanel.Visible =False End Select End Sub Protected Sub viewTabContainer_ActiveTabChanged(ByVal senderAs Object,ByVal eAs System.EventArgs)'The trouble code. Only by changing the tabs the code is execute twice. checkView("tabs")'Rebuild tab contentsEnd Sub Private Sub getView()'A lot of code to get the dataEnd Sub Private Sub checkView(ByVal typeAs String)If type ="all"Or type ="tabs"Then Select Case viewTabContainer.ActiveTabIndexCase 0Case 1
 Dim drAs New Deelnemer_relatie dr.getRelaties(d.id, relatieViewPlaceHolder)
Case 2Case 3End Select End If If type ="all"Or type ="buttons"Then If d.nieuwThen toevoegenButton.Enabled =False Else toevoegenButton.Enabled =True End If End If Page.Validate()End Sub Private Sub setDeelnemer()'A lot of code to save the data d.opslaan()End Sub Private Sub getTaal()Dim tAs New Taal'Get the languageEnd SubEnd Class

Code description:

The page is a simple page that allow changes to a table with students. On the second tab there is a view with different relations. The relations view is a bit heavy for the DB so I only want to load the data when the user is actualy see te tab. Problem is when the user clicks the tab the code is fired twice. (reloads etc is no problem).

Edit: Oeps forget before and after de aspx...

Before the ASPX:

<%@. Page Language="VB" MasterPageFile="~/Beheer/MasterPage.master" AutoEventWireup="false" CodeFile="Deelnemer.aspx.vb"Inherits="Beheer_Deelnemer_Deelnemer" Theme="Blauw" %><%@. RegisterAssembly="AjaxControlToolkit"Namespace="AjaxControlToolkit" TagPrefix="cc1" %><%@. MasterType VirtualPath="~/Beheer/MasterPage.master" %><asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> <asp:UpdatePanel ID="UpdatePanel" UpdateMode="Conditional" runat="server"> <ContentTemplate> <asp:HiddenField ID="idHidden" Value="0" runat="server" /> <asp:HiddenField ID="nieuwHidden" Value="False" runat="server" /> <asp:HiddenField ID="wijzigingenHidden" Value="False" runat="server" /> <div class="viewTitle"> <asp:Label ID="viewTitelLabel" runat="server"></asp:Label> </div> <table width="100%"> <tr> <td rowspan="2">
After the ASPX:
 </td> <td class="menuTop"> <asp:Button CssClass="viewButton" ID="toevoegenButton" runat="server" OnClick="toevoegenButton_Click" CausesValidation="False" /> </td> </tr> <tr> <td class="menuBottom"> <asp:Button CssClass="viewButton" ID="terugButton" runat="server" OnClick="terugButton_Click" CausesValidation="False" /> <asp:Button CssClass="viewButton" ID="wijzigButton" OnClick="wijzigButton_Click" runat="server" CausesValidation="True"></asp:Button> </td> </tr> </table> <asp:Button CssClass="viewButton" ID="navigeerEersteButton" Text="|<" runat="server" OnClick="navigatie_Click" CausesValidation="False" EnableViewState="false" /> <asp:Button CssClass="viewButton" ID="navigeerVorigeButton" Text="<" runat="server" OnClick="navigatie_Click" CausesValidation="False" EnableViewState="false" /> <asp:Button CssClass="viewButton" ID="navigeerVolgendeButton" Text=">" runat="server" OnClick="navigatie_Click" CausesValidation="False" EnableViewState="false" /> <asp:Button CssClass="viewButton" ID="navigeerLaatsteButton" Text=">|" runat="server" OnClick="navigatie_Click" CausesValidation="False" EnableViewState="false" /> <asp:Panel ID="alertPanel" runat="server" ScrollBars="Auto" Visible="false" CssClass="alertPanel" EnableViewState="false"> <asp:ImageButton ID="alertImageButton" runat="server" CausesValidation="False" CssClass="alertButton" EnableViewState="False" ImageUrl="~/App_Themes/Blauw/Sluiten.gif" OnClick="alertImageButton_Click" /> <asp:ValidationSummary ID="viewValidationSummary" runat="server" ShowMessageBox="false" ShowSummary="true" ValidationGroup="view" EnableViewState="false" Visible="false" /> <asp:Label ID="alertLabel" runat="server" Visible="false"></asp:Label> </asp:Panel> </ContentTemplate> </asp:UpdatePanel></asp:Content>

Don't know why but if I select a different tab the OnActiveTabChanged fires twice and when I select the active tab it only runs once (don't even know if that's normal).


The problem happens when the TabContainer is inside the UpdatePanel. Here is a cleaner version that includes the problem.

I'll try to figure out how to solve it.

<%@. 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"> public static int count = 0; protected void TabContainer1_ActiveTabChanged(object sender, EventArgs e) { count++; Label1.Text = count.ToString(); }</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> <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> <ajaxToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="3" OnActiveTabChanged="TabContainer1_ActiveTabChanged" AutoPostBack="True"> <ajaxToolkit:TabPanel ID="TabPanel1" runat="server" HeaderText="TabPanel1"> </ajaxToolkit:TabPanel> <ajaxToolkit:TabPanel ID="TabPanel2" runat="server" HeaderText="TabPanel2"> </ajaxToolkit:TabPanel> <ajaxToolkit:TabPanel ID="TabPanel3" runat="server" HeaderText="TabPanel3"> </ajaxToolkit:TabPanel> <ajaxToolkit:TabPanel ID="TabPanel4" runat="server" HeaderText="TabPanel4"> </ajaxToolkit:TabPanel> </ajaxToolkit:TabContainer> </ContentTemplate> </asp:UpdatePanel>   </div>   </form></body></html>

My guess is that the event fires after an async postback (because it remembers the active tab and switches to that immediately), so it's firing once when the tab changes, and then again when the async postback completes.

A simple test for this would be to put a sleep statement in Page_Load on the server and observe if there's a time gap between the events firing.


Hi Steve,

Both events fired after the page_load. So, can't see a time gap.

An interesting finding is that the stack trace of the events are different, one is rooted from TabContainer.IPostBackEventHandler.RaisePostBackEvent, the other one is from scriptControlBase.IPostBackDataHandler.RaisePostDataChangedEvent.


Oh, sorry; I thought you were talking about the client-side event... now I see what you're saying!


Raymond, please feel free to open a work item if you believe this to be a bug in the Toolkit. Thanks for the help!


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


I am having this same issue. Has anyone came up with a workaround?


Private tempAs boolean = false
Protected Sub viewTabContainer_ActiveTabChanged(ByVal senderAs Object,ByVal eAs System.EventArgs)If temp = falseThen temp = true
'Code
End If End Sub

Well, where do you reset the temp variable? In your case the event handler will execute the needed code only once. :)

I think there's no suited "workaround" for this problem, because one need to distinguish between the two root sources for the event raising, and this seems to be not possible...

Kind regards,

sbogus.


Private tempEenmaligAs Boolean =True'Tijdelijk ivm bug in TabsProtected Sub viewTabContainer_ActiveTabChanged(ByVal senderAs Object,ByVal eAs System.EventArgs)'Deze code wordt om een vage reden 2 keer uitgevoerd. Post geplaats op ASP.net 'http://forums.asp.net/p/1133367/1811883.aspx 'Tijdelijk een tempEenmalig gebruikt.If tempEenmaligThen tempEenmalig =False checkView("tabs")'Tab opnieuw opbouwenEnd If End Sub

This exacly my code to avoid the problem. After te postback te page wil reload and "Private tempEenmaligAs Boolean =True" will run again and set to False so the code wil run once.
Works fine for me so don't know what your problem is...

No comments:

Post a Comment