Quantcast
Channel: ASP.NET AJAX + Ajax Control Toolkit (ACT)
Viewing all articles
Browse latest Browse all 5678

expandable/collapsible grid using CollapsiblePanelExtender and DynamicPopulateExtender

$
0
0

Like many before me I have been trying to implement a tidy expandable/collapsible gridview where, for example, the grid initially shows a list of writers and on clicking on a suitable 'expand' button in a row the writer's works are dynamically retrieved from the database and displayed. Actually I have managed to get a reasonably tidy version to work using the Ajax Toolkit CollapsiblePanelExtender and DynamicPopulateExtender in combination with minimal additional Javascript. In case it is of any use to anyone, the key elements are as follows:

<asp:GridView runat="server" ID="Writers" DataSourceID="WritersDS" DataKeyNames="PersonID" PageSize='<%$ AppSettings: GridPageSize %>' ><Columns><asp:TemplateField ShowHeader="False" ItemStyle-VerticalAlign="Top"><ItemTemplate><asp:Image ID="ShowWorksButton" runat="server" /><ajaxToolkit:DynamicPopulateExtender ID="DPE" runat="server" PopulateTriggerControlID="ShowWorksButton" CacheDynamicResults="false" ClearContentsDuringUpdate="true" EnableViewState="False"
            ServiceMethod="GetWorks" ContextKey='<%# Eval("PersonID") %>' TargetControlID="WorksPanel" /></ItemTemplate></asp:TemplateField><asp:TemplateField HeaderText="writer" SortExpression="Surname" ItemStyle-Width="200" ItemStyle-VerticalAlign="Top"><ItemTemplate><asp:Label ID="hName" runat="server" Text='<%# Eval("Name")%>' /></ItemTemplate></asp:TemplateField><asp:TemplateField ItemStyle-Width="750"><ItemTemplate><asp:Panel ID="WorksPanel" runat="server" EnableViewState="false" style="height:auto;min-height:36px;max-height:124px;overflow:auto"/><ajaxToolkit:CollapsiblePanelExtender ID="CPE" ClientIDMode="Static" runat="server" TargetControlID="WorksPanel" ExpandControlID="ShowWorksButton" CollapseControlID="ShowWorksButton"
            ImageControlID="ShowWorksButton" CollapsedImage="~/images/expand.png" ExpandedImage="~/images/collapse.png"
            Collapsed="True" CollapsedSize="0" ExpandedSize="124" ScrollContents="True" AutoCollapse="False" AutoExpand="False" /></ItemTemplate></asp:TemplateField></Columns>

And in code behind:

<WebMethod()> _<ScriptMethod()> _
    Public Shared Function GetWorks(ByVal contextKey As String) As String
        Dim dal As New DAL
        Dim personid As Integer = CInt(contextKey)
        Dim html As StringBuilder = New StringBuilder
        html.Append("<table><col width='480px'</col><col width='70px'</col><col width='110px'</col><col width='35px'</col><col width='50px'</col>")
        html.Append("<tr><th style='text-align:left;'>title</th><th style='text-align:left;'>form</th><th style='text-align:left;'>genre</th><th>written</th><th>owned</th></tr>")
        Dim works As List(Of LiteraryWorkInfo) = dal.GetSelectedWorksByWriter(personid)
        Dim owned As String = ""
        For Each work As LiteraryWorkInfo In works
            html.Append("<tr><td><a href='workform.aspx?id=" & work.WorkID.ToString() & "'>" & work.Title & "</a></td><td>" & work.Form & "</td><td>" & work.Genre & "</td><td style='text-align:center'>" & work.Written & "</td><td style='text-align:center'>" & work.Owned & "</td></tr>")
        Next
        html.Append("</table>")
        Return html.ToString()
    End Function

It is also necessary to make the CPE IDs unique (it is probably possible to do this declaratively):

    Protected Sub WireUpWorks(ByVal s As Object, ByVal e As GridViewRowEventArgs) Handles Writers.RowCreated
        If e.Row.RowType = DataControlRowType.DataRow Then
            Dim cpe As CollapsiblePanelExtender = CType(e.Row.FindControl("CPE"), CollapsiblePanelExtender)
            Dim id As String = String.Concat("CPE", e.Row.RowIndex)
            cpe.BehaviorID = id
        End If
    End Sub

And like others I have found it necessary to add some Javascript to smooth the animation (why this could not have been the default or at least easily changeable I do not know) and to provide an accordion-like effect:

function pageLoad(sender, args) {
    for (num = 0; num < 20; num++) {
        var cpe = $find("CPE" + num);
        if (cpe) {
            cpe.add_expanding(accordion);
            cpe._animation._fps = 45;
            cpe._animation._duration = 0.4;
        }
    }
}
function accordion(sender, arg) {
    for (num = 0; num < 20; num++) {
        var cpe = $find("CPE" + num);
        if (cpe) {
            if (sender._expandControlID != cpe._expandControlID)
                cpe.collapsePanel(cpe._expandControlID);
        }
    }
}

All of this works surprisingly well, but there are some irritating aspects which I have not been able to fix. I have limited the maximum height of the works panel in order to prevent the overall height of the grid causing vertical scrolling of the page. But what I would really like is for the CPE ExpandedSize to reflect the actual height of the panel (i.e. equivalent to 'auto'). But this does not appear possible and I have had to set ExpandedSize to the same value as the panel's maximum height (not setting ExpandSize at all has the surprising effect of causing the panel to pop out to the full size of the actual content with no animation, completely ignoring the CSS on the panel itself). As a result, the panel always expands to this height even if there is less actual content. And what is even more irritating is that there is a 'disabled' vertical scrollbar in the panel even if no scrolling is required (and if I remove ScrollContents="True" from the extender then, perhaps less surprisingly, there is no scrolling, despite the panel CSS). What I do not know is whether this is a CSS issue or something to do with the extender. Either way, I would be grateful for any suggestions how to fix this.

Jon


Viewing all articles
Browse latest Browse all 5678

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>