Search code examples
asp.netvb.netcollapsiblepanelextender

ASP.Net 3.5 AjaxControlToolkit CollapsiblePanelExpander in Master In UpdatePanel partial postback woes


Long time reader first time poster

I have a content page linked to a master page. The master has the toolkitscriptmanager. On the content page, I have a nested repeater within the item template of the parent repeater, I have a CollapsiblePanelExtender for the child repeater control. Upon partial postback, if the collapsed attribute is not set, then all of the panels expand. If the collapsed attribute is set to true, then all of the panels are collapsed upon partial postback.

The databinding of the repeater is occurring in the page_init section of the code behind, and I am checking the state of the panels by iterating through the items in the page_load event. Nothing appears to be working, while debugging the code, I do see the properties being appropriately set, but when rendered in the browser, all panels are open. The edit event that triggers the partial postback is preformed in a modalpopup.

I have attempted to move the panels into their own update panel, remove the update panel, place the modal outside of the update panel to no avail. The ViewState is not maintained.

Page Code:

<asp:Repeater ID="rptrConsultants" runat="server" OnItemCommand="rptrConsultants_ItemCommand" OnItemDataBound="rptrConsultants_ItemDataBound">
                            <HeaderTemplate>
                                <div class="pageTitle">
                                    Your Consultants (Click on the image beside the consultant to view their group memberships)
                                    <br />
                                    Official names are listed. Expanding the consultant will show the name assigned and the related groups.
                                </div>
                                <br />
                                <table>
                                    <tr>
                                        <td style="width: 60px; font-weight: bold; text-align: center;">
                                            Actions
                                        </td>
                                        <td style="font-weight: bold;">
                                            Consultant information
                                        </td>
                                    </tr>
                            </HeaderTemplate>
                            <FooterTemplate>
                                </table>
                                <asp:Label ID="lblNoConsultant" runat="server" Text="You have not created any consultants" Visible="false"></asp:Label>
                            </FooterTemplate>
                            <ItemTemplate>
                                <tr>
                                    <td style="width: 60px; text-align: center;">
                                        <asp:Image ID="imgConsultantExpander" runat="server" ToolTip="Click here to toggle consultant details" AlternateText="Toggle Consultant Details" />
                                        <asp:ImageButton ID="btnDeleteConsultant" AlternateText="Delete Consultant" runat="server" CausesValidation="false" CommandName="DeleteConsultant" CommandArgument='<%#DataBinder.Eval(Container.DataItem, "IndividualsID")%>' ImageUrl="~/Styles/Images/Icons/remove_consultant.png" ToolTip="Delete consultant" />
                                        <asp:ImageButton ID="btnAddConsultantToNewGroup" AlternateText="Add consultant to a new group" runat="server" CommandName="AddConsultantToGroup" CommandArgument='<%#DataBinder.Eval(Container.DataItem, "IndividualsID")%>' ImageUrl="~/Styles/Images/Icons/add_user_to_group.png" ToolTip="Add consultant to a new group" />
                                    </td>
                                    <td>
                                        <%#DataBinder.Eval(Container.DataItem, "Name")%>
                                        (<%#DataBinder.Eval(Container.DataItem, "UserID") %>)
                                        <asp:Label ID="lblGroupCount" runat="server" />
                                    </td>
                                </tr>
                                <tr>
                                    <td colspan="2">
                                        <asp:Panel ID="pnlConsultantExpander" runat="server">
                                            <asp:Repeater ID="rptrConsultantGroups" runat="server" DataSource='<%#Container.DataItem.Row.GetChildRows("ConsultantGroupRelation") %>' OnItemCommand="rptrConsultantGroups_ItemCommand">
                                                <HeaderTemplate>
                                                    <table style="margin-left: 50px;">
                                                        <tr>
                                                            <td style="width: 40px; text-align: center; font-weight: bold;">
                                                                Actions
                                                            </td>
                                                            <td style="font-weight: bold;">
                                                                Membership
                                                            </td>
                                                            <td style="font-weight: bold;">
                                                                Nick Name
                                                            </td>
                                                        </tr>
                                                </HeaderTemplate>
                                                <ItemTemplate>
                                                    <tr>
                                                        <td style="width: 40px;">
                                                            <asp:ImageButton ID="btnEditConsultant" AlternateText="Edit Consultant" runat="server" CommandName="EditConsultantInGroup" CommandArgument='<%#Container.DataItem("GroupID") & "|" & Container.DataItem("GroupMembershipID")%>' ImageUrl="~/Styles/Images/Icons/edit_consultant.png" />
                                                            <asp:ImageButton ID="btnDeleteConsultant" AlternateText="Remove from group" runat="server" CommandName="DeleteConsultantFromGroup" CommandArgument='<%#Container.DataItem("GroupID") & "|" & Container.DataItem("GroupMembershipID")%>' ImageUrl="~/Styles/Images/Icons/delete_fromgroup.png" ToolTip="Remove from group" />
                                                        </td>
                                                        <td class="textbold">
                                                            <%#Container.DataItem("GroupName")%>
                                                        </td>
                                                        <td class="textitalic">
                                                            <%#Container.DataItem("nickname")%>
                                                        </td>
                                                    </tr>
                                                </ItemTemplate>
                                                <FooterTemplate>
                                                    </table>
                                                </FooterTemplate>
                                            </asp:Repeater>
                                        </asp:Panel>
                                        <asp:CollapsiblePanelExtender ID="cpepnlConsultantExpander" runat="server" TargetControlID="pnlConsultantExpander" CollapseControlID="imgConsultantExpander" ExpandControlID="imgConsultantExpander" CollapsedImage="~/Styles/Images/Icons/user_info.png" ExpandedImage="~/Styles/Images/Icons/user_open.png" ImageControlID="imgConsultantExpander" EnableViewState="true" CollapsedSize="0" />
                                    </td>
                                </tr>
                            </ItemTemplate>
                        </asp:Repeater>

And then the code behind method that occurs in page_load:

Private Sub setCollapsiblePanelsInRepeater(ByVal rptr As Repeater)
    For Each item As RepeaterItem In rptr.Items
        If ((item.ItemType = ListItemType.AlternatingItem) Or (item.ItemType = ListItemType.Item)) Then
            For Each ctl As Control In item.Controls
                If (TypeOf ctl Is AjaxControlToolkit.CollapsiblePanelExtender) Then
                    Dim cpe As AjaxControlToolkit.CollapsiblePanelExtender = DirectCast(ctl, AjaxControlToolkit.CollapsiblePanelExtender)
                    If (Not IsPostBack()) Then
                        cpe.Collapsed = True
                        cpe.ClientState = "true"
                    Else
                        Dim isCollapsed As Boolean
                        If (Request.Form(cpe.UniqueID & "_ClientState") IsNot Nothing) Then
                            isCollapsed = (Request.Form(cpe.UniqueID & "_ClientState").ToString() = "true")
                        Else
                            isCollapsed = True
                        End If
                        If (isCollapsed) Then
                            cpe.ClientState = "true"
                            cpe.Collapsed = True
                        Else
                            cpe.ClientState = "false"
                            cpe.Collapsed = False
                        End If
                    End If
                End If
            Next
        End If
    Next
End Sub

Note that the initial load event works! The panels are all collapsed on page load

Also note, that the repeater is nested in a tabPanel

Thank you in advance for your answer!

sorry for the long winded explanation

EDIT:

Update:

Attempted the Javascript Route -- Still no avail

    pageLoad = function()
    {
            CheckStatusOfPanels();
    };

    function CheckStatusOfPanels()
    {
        var allBehaviors = Sys.Application.getComponents();
        for (var loopIndex = 0; loopIndex < allBehaviors.length; loopIndex++)
        {
            currentBehavior = allBehaviors[loopIndex];
            if (currentBehavior._name && currentBehavior.get_name() == 'CollapsiblePanelBehavior')
            {
                var myID = currentBehavior.get_id() + '_ClientState';
                var isCollapsed = document.getElementById(myID).value
                if (isCollapsed == 'true')
                {
                    currentBehavior.expandPanel();
                    currentBehavior._ClientState = isCollapsed;
                }
                else
                {
                    currentBehavior.collapsePanel();
                    currentBehavior._ClientState = isCollapsed;
                }
            }
        }
    }

** UPDATE #2 **

My Rep is under 100 so I have to wait 8 hrs for the ability to answer my own question:

Here is my "fix" after working almost all day on this:

Ok finally found a solution. Here it goes:

Using the SetCollapsiblePanelsInRepeater method posted in my original post, I added the call to this method in the updatePanel prerender method, and Voila the panels now preserve their state....

Protected Sub updtpnlMain_PreRender(ByVal sender As Object, ByVal e As EventArgs) Handles updtpnlMain.PreRender
    setCollapsiblePanelsInRepeater(rptrGroups)
    setCollapsiblePanelsInRepeater(rptrConsultants)

End Sub

For Clarity for others Googling this issue, the method that sets the panel events is:

Private Sub setCollapsiblePanelsInRepeater(ByVal rptr As Repeater)
    For Each item As RepeaterItem In rptr.Items
        If ((item.ItemType = ListItemType.AlternatingItem) Or (item.ItemType = ListItemType.Item)) Then
            For Each ctl As Control In item.Controls
                If (TypeOf ctl Is AjaxControlToolkit.CollapsiblePanelExtender) Then
                    Dim cpe As AjaxControlToolkit.CollapsiblePanelExtender = DirectCast(ctl, AjaxControlToolkit.CollapsiblePanelExtender)
                    If (Not IsPostBack()) Then
                        cpe.Collapsed = True
                        cpe.ClientState = "true"
                    Else
                        Dim isCollapsed As Boolean
                        If (Request.Form(cpe.UniqueID & "_ClientState") IsNot Nothing) Then
                            isCollapsed = (Request.Form(cpe.UniqueID & "_ClientState").ToString() = "true")
                        Else
                            isCollapsed = True
                        End If
                        If (isCollapsed) Then
                            cpe.ClientState = "true"
                            cpe.Collapsed = True
                        Else
                            cpe.ClientState = "false"
                            cpe.Collapsed = False
                        End If
                    End If
                End If
            Next
        End If
    Next
End Sub

Solution

  • Ok finally found a solution. Here it goes:

    Using the SetCollapsiblePanelsInRepeater method posted in my original post, I added the call to this method in the updatePanel prerender method, and Voila the panels now preserve their state....

    Protected Sub updtpnlMain_PreRender(ByVal sender As Object, ByVal e As EventArgs) Handles updtpnlMain.PreRender
        setCollapsiblePanelsInRepeater(rptrGroups)
        setCollapsiblePanelsInRepeater(rptrConsultants)
    
    End Sub
    

    For Clarity for others Googling this issue, the method that checks the status of the panels and collapses / expands them is:

    Private Sub setCollapsiblePanelsInRepeater(ByVal rptr As Repeater) For Each item As RepeaterItem In rptr.Items If ((item.ItemType = ListItemType.AlternatingItem) Or (item.ItemType = ListItemType.Item)) Then For Each ctl As Control In item.Controls If (TypeOf ctl Is AjaxControlToolkit.CollapsiblePanelExtender) Then Dim cpe As AjaxControlToolkit.CollapsiblePanelExtender = DirectCast(ctl, AjaxControlToolkit.CollapsiblePanelExtender) If (Not IsPostBack()) Then cpe.Collapsed = True cpe.ClientState = "true" Else Dim isCollapsed As Boolean If (Request.Form(cpe.UniqueID & "_ClientState") IsNot Nothing) Then isCollapsed = (Request.Form(cpe.UniqueID & "_ClientState").ToString() = "true") Else isCollapsed = True End If If (isCollapsed) Then cpe.ClientState = "true" cpe.Collapsed = True Else cpe.ClientState = "false" cpe.Collapsed = False End If End If End If Next End If Next End Sub