Double click AJAX Accordion bug
Saturday, December 13th, 2008This post will be a short one summarizing a work around for the double click problem associated with the accordion control from the ASP.NET Ajax Control Toolkit. This problem occurs when controls are placed within the panes of the accordion control. When the page is loaded it takes two clicks of the control before the actual click event will be invoked.
Lets recreate an example to demonstrate and recreate this problem. First we will create an accordion and assign a button and label within its content template. The label we will use to test when our event is actually invoked. I will use my previous post’s books catalog example for this.
<ajaxToolkit:Accordion
ID="accordionBooks"
runat="server"
SelectedIndex="0"
HeaderCssClass="accordionHeader"
HeaderSelectedCssClass="accordionHeaderSelected"
ContentCssClass="accordionContent"
FadeTransitions="false"
FramesPerSecond="40"
TransitionDuration="250"
AutoSize="None"
RequireOpenedPane="false"
SuppressHeaderPostbacks="true"
onitemdatabound="accordionBooks_ItemDataBound">
<HeaderTemplate>
<p>
<asp:Literal ID="litCategory" runat="server" Text="Category:" />
<asp:Label ID="lblBookCategory" Text='<%# DataBinder.Eval(Container.DataItem, "category_name") %>' runat="server" />
</p>
</HeaderTemplate>
<ContentTemplate>
<asp:HiddenField ID="hdnCategoryId" Value='<%# DataBinder.Eval(Container.DataItem, "id") %>' runat="server" />
<asp:Label ID="lblInvokeStatus" Text="Not Invoked" runat="server" />
<asp:Button ID="btnInvokeEvent" runat="server" Text="Invoke Event" OnClick="OnClickInvoke" />
</ContentTemplate>
</ajaxToolkit:Accordion>
And the code behind event…
protected void OnClickInvoke(object sender, EventArgs e)
{
Label invokeLabel = (Label)
accordionBooks.Panes[accordionBooks.SelectedIndex].FindControl("lblInvokeStatus");
invokeLabel.Text = "Invoked!";
}
Now, if you were to run the above code on a databound accordion you should see the double click problem occuring. The label will not change until the second click, but after that it will work each consecutive time.
So what I will now do is fake the button click, by applying our asp button outside our accordion where it will not be affected, and then force its click event from a button within the accordion using some javascript.
<asp:Button ID="btnInvokeEvent" runat="server" Text="Invoke Event" OnClick="OnClickInvoke" />
<ajaxToolkit:Accordion
ID="accordionBooks"
runat="server"
SelectedIndex="0"
HeaderCssClass="accordionHeader"
HeaderSelectedCssClass="accordionHeaderSelected"
ContentCssClass="accordionContent"
FadeTransitions="false"
FramesPerSecond="40"
TransitionDuration="250"
AutoSize="None"
RequireOpenedPane="false"
SuppressHeaderPostbacks="true"
onitemdatabound="accordionBooks_ItemDataBound">
<HeaderTemplate>
<p>
<asp:Literal ID="litCategory" runat="server" Text="Category:" />
<asp:Label ID="lblBookCategory" Text='<%# DataBinder.Eval(Container.DataItem, "category_name") %>' runat="server" />
</p>
</HeaderTemplate>
<ContentTemplate>
<asp:HiddenField ID="hdnCategoryId" Value='<%# DataBinder.Eval(Container.DataItem, "id") %>' runat="server" />
<asp:Label ID="lblInvokeStatus" Text="Not Invoked" runat="server" />
<input type="button" value="Invoke Event" onclick="javascript:$get('<%= btnInvokeEvent.UniqueID %>').click();" />
</ContentTemplate>
</ajaxToolkit:Accordion>
And now the click event should fire on the first click. When I tested this on an accordion with the panes hardcoded the bug didn’t show up, so it is likely that you will not need to use this workaround unless you are data binding your accordion. Hope this helped.