1
votes

I have a setup using three levels of nesting: A Repeater, the items of which utilize CollapsiblePanelExtenders (which work), and each contain a GridView. Each of these then contain another GridView which is controlled by another CollapsiblePanelExtender. These inner CollapsiblePanels will effectively show either an expanded or collapsed state only if I set clientState to True. However, they do not effectively expand or collapse as expected. Everything is bound dynamically.

Here is the markup...

<asp:Repeater ID="cat_repeater" runat="server">
  <ItemTemplate>
    <asp:CollapsiblePanelExtender id="cat_cpExt" runat="server" TargetControlID="cat_pnl" CollapsedSize="0" Collapsed="false" CollapsedImage="collapsed.png" ExpandedImage="expanded.png" ExpandControlID="cpControl_pnl" CollapseControlID="cpControl_pnl" TextLabelID="cpControl_lbl" ImageControlID="cpControl_img" CollapsedText='<%#configCPText(eval("Title"), False)%>' ExpandedText='<%#configCPText(eval("Title"), True) %>' />
    <asp:Panel ID="cpControl_pnl" runat="server" Visible='<%#itemVisible(eval("ID"), "Recipients", "CategoryID") %>' CssClass="CPanelStyle">
      <asp:Image ID="cpControl_img" runat="server" ImageUrl="expanded.png" />
      <asp:Label ID="cpControl_lbl" runat="server" Text='<%#configCPText(eval("Title"), True) %>' CssClass="CPanelText" />
    </asp:Panel>
    <asp:Panel ID="cat_pnl" runat="server">
      <asp:GridView ID="recipients_gv" runat="server" CssClass="GVStyle" HeaderStyle-CssClass="GVHeaderStyle" RowStyle-CssClass="GVItemStyle" AutoGenerateColumns="false" GridLines="none" AllowPaging="false">
        <Columns>
          <asp:TemplateField HeaderText="Name" SortExpression="Last Name" ItemStyle-CssClass="GVNameStyle">
            <ItemTemplate>
              <asp:Literal id="name_lit" runat="server" text='<%#formatNameText(eval("FirstName"), eval("LastName")) %>' />
            </ItemTemplate>
          </asp:TemplateField>
          <asp:TemplateField HeaderText="Gifts" ItemStyle-Width="500px">
            <ItemTemplate>
              <asp:CollapsiblePanelExtender id="gifts_cpExt" runat="server" TargetControlID="gifts_pnl" CollapsedSize="0" Collapsed="true" CollapsedImage="collapsed.png" ExpandedImage="expanded.png" ExpandControlID="cpControl_pnl2" CollapseControlID="cpControl_pnl2" TextLabelID="cpControl_lbl2" ImageControlID="cpControl_img2" CollapsedText='<%#configGiftsCPText(eval("ID"), True)%>' ExpandedText='<%#configGiftsCPText(eval("ID"), False) %>' />
              <asp:Panel ID="cpControl_pnl2" runat="server" Visible='<%#itemVisible(eval("ID"), "Gifts", "RecipientID") %>'>
                <asp:Image ID="cpControl_img2" runat="server" ImageUrl="collapsed.png" />
                <asp:Label ID="cpControl_lbl2" runat="server" Text='<%#configGiftsCPText(eval("ID"), False) %>' />
              </asp:Panel>
              <asp:Panel ID="gifts_pnl" runat="server">
                <asp:GridView ID="gifts_gv" runat="server" DataKeyNames="ID" RowStyle-CssClass="GVInnerItemStyle" HeaderStyle-CssClass="GVInnerHeaderStyle" Gridlines="None" AutoGenerateColumns="false" AllowPaging="false" Width="475px">
                  <Columns>
                    <asp:TemplateField ItemStyle-CssClass="GVInnerButtonItemStyle" HeaderText="Description">
                      <ItemTemplate>
                        <asp:LinkButton ID="gift_lBtn" runat="server" Text='<%#eval("Description") %>' CommandName="Select" />
                      </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Complete" ItemStyle-Width="50px">
                      <ItemTemplate>
                        <asp:CheckBox ID="giftComplete_cbx" runat="server" Checked='<%#eval("Complete") %>' />
                      </ItemTemplate>
                    </asp:TemplateField>
                  </Columns>
                </asp:GridView>
              </asp:Panel>
            </ItemTemplate>
          </asp:TemplateField>
        </Columns>
      </asp:GridView>
    </asp:Panel>
    <br />
  </ItemTemplate>
</asp:Repeater>

...And here is the code to bind everything:

Protected Sub bindCategories()

    Try
        oCmd.Connection = oConn
        oCmd.CommandType = CommandType.Text

        strSQL = "SELECT * FROM Categories"

        oCmd.CommandText = strSQL
        oDA.SelectCommand = oCmd

        oDA.Fill(oDTbl)

        cat_repeater.DataSource = oDTbl
        cat_repeater.DataBind()

        For i As Integer = 0 To oDTbl.Rows.Count - 1


            oCmd.Parameters.Clear()
            inner_dTbl.Clear()

            strSQL = "SELECT *, Title FROM Recipients INNER JOIN Categories on Recipients.CategoryID = Categories.ID WHERE CategoryID = @CategoryID ORDER BY LastName"

            oParam = New SqlParameter
            oParam.ParameterName = "CategoryID"
            oParam.SqlDbType = SqlDbType.Int
            oParam.Value = oDTbl.Rows(i)("ID")
            oCmd.Parameters.Add(oParam)

            oCmd.CommandText = strSQL
            oDA.SelectCommand = oCmd

            oDA.Fill(inner_dTbl)

            Dim gv As GridView = CType(cat_repeater.Items(i).FindControl("recipients_gv"), GridView)
            gv.DataSource = inner_dTbl
            gv.DataBind()

            For j As Integer = 0 To inner_dTbl.Rows.Count - 1

                oCmd.Parameters.Clear()
                gifts_dTbl.Clear()

                strSQL = "SELECT * FROM Gifts WHERE RecipientID = @RecipientID ORDER BY Description"

                oParam = New SqlParameter
                oParam.ParameterName = "RecipientID"
                oParam.SqlDbType = SqlDbType.Int
                oParam.Value = inner_dTbl.Rows(j)("ID")
                oCmd.Parameters.Add(oParam)

                oCmd.CommandText = strSQL
                oDA.SelectCommand = oCmd

                oDA.Fill(gifts_dTbl)

                Dim inner_gv As GridView = CType(gv.Rows(j).FindControl("gifts_gv"), GridView)
                inner_gv.DataSource = gifts_dTbl
                inner_gv.DataBind()

                Dim cpExt As CollapsiblePanelExtender = CType(gv.Rows(j).FindControl("gifts_cpExt"), CollapsiblePanelExtender)
                cpExt.Collapsed = True
                cpExt.ClientState = True

            Next

        Next
    Catch ex As Exception
        Throw ex
    End Try

End Sub

I've successfully used CollapsiblePanelExtenders in a 2-level nested GridView setup that without a problem before, and without having to set clientState. However, I've had to specify clientState when using CollapsiblePanelExtenders with Repeaters before.

Does anyone have any input regarding why these extenders will not function in this 3-level nested setup?

1

1 Answers

0
votes

It looks like the reason it's required is because it needs a postback to make all that logic work:

if (this.SupportsClientState) {
  ScriptManager.RegisterHiddenField(this, this.ClientStateFieldID, this.SaveClientState());
  this.Page.RegisterRequiresPostBack(this);
}

This is from public class ScriptControlBase in the AjaxControlToolkit space.

Are you wrapping this in an UpdatePanel? Does it cause a postback to use the CPE in the repeater? It's been awhile since I've tried to do a CPE in a repeater, and I'm not setup at this point to check the code out and build one.

Is there a reason you can't just use something completely client-side and just expand/collapse these using javascript? Are you loading data dynamically server side when these things get expanded?