Expand/Collapse issues using Grouping

4 posts, 0 answers
  1. Curtis
    Curtis avatar
    2 posts
    Member since:
    Feb 2012

    Posted 27 Feb 2012 Link to this post

    We recently upgraded from the ASP.NET Classic controls to the ASP.NET AJAX controls on one of our largest projects.  One of our requirements was to maintain current behavior and appearance on all controls.  Unfortuantely, we are having a fair amount of trouble with RadGrids. 

    We are using a RadGrid with server side grouping and expand/collapse functionality enabled.  When a user expands/collapses an item, the ItemCommand event is fired which updates a session variable to keep track of which items are expanded.  When the user returns to the page, the ItemDataBound method determines whether or not to expand a GridGroupHeaderItem depending on the values stored in the session variable.  The good news is that expanded/collapsed states are rendering correctly on subsequent page loads.  Unfortunately, if the user then expands or collapses any item, all GridItems that were expanded in the ItemDataBound disappear.  The groups that these items belong to are still expanded and items that have been expanded after page load are not affected.  Clicking on the group again collapses the group with the missing items, and the next click re-expands it revealing the items that were missing.

    Does anyone have any idea why our items are being hidden?  I included snippets from the aspx and aspx.cs files below.  Specific names and details have been changed to protect the innocent.

    ...
     
    <telerik:RadAjaxManager runat="server" ID="radAjaxManager" EnableAJAX="true" OnAjaxRequest="RadAjaxManager_AjaxRequest">
        <AjaxSettings>
            <telerik:AjaxSetting AjaxControlID="radAjaxManager">
                <UpdatedControls>
                    <telerik:AjaxUpdatedControl ControlID="radGrid1" />
                </UpdatedControls>
            </telerik:AjaxSetting>
        </AjaxSettings>
    </telerik:RadAjaxManager>
     
    ...
     
    <telerik:RadGrid ID="radGrid1" runat="server" AllowFilteringByColumn="false" AllowPaging="false" AllowSorting="true" AutoGenerateColumns="false" EnableEmbeddedSkins="false" GroupingEnabled="true"
        OnItemCommand="radGrid1_ItemCommand" OnItemDataBound="radGrid1_ItemDataBound" OnNeedDataSource="radGrid1_NeedDataSource"
        ShowGroupPanel="false" ShowHeader="true" Skin="XYZ">
        <ClientSettings AllowColumnsReorder="true" AllowGroupExpandCollapse="true" AllowDragToGroup="false" ReorderColumnsOnClient="true">
            <Resizing AllowColumnResize="false" AllowRowResize="false" EnableRealTimeResize="false" ResizeGridOnColumnResize="false"/>
            <ClientEvents OnGridCreated="radGrid1_GridCreated" />
        </ClientSettings>
        <MasterTableView AllowMultiColumnSorting="false" DataKeyNames="Data1, Data2"
            GroupLoadMode="Server" GroupsDefaultExpanded="false" ShowHeader="true" Name="mtvRadGrid1"
            NoDetailRecordsText="There are no items that match your request."
            NoMasterRecordsText="There are no items that match your request." ShowFooter="false">
            <GroupByExpressions>
                <telerik:GridGroupByExpression>
                    <SelectFields>
                        <telerik:GridGroupByField Aggregate="First" FieldAlias="Group1NameAlias" FieldName="Group1Name"/>
                        <telerik:GridGroupByField Aggregate="First" FieldAlias="Group1IdAlias" FieldName="Group1Id"/>
                    </SelectFields>
                    <GroupByFields>
                        <telerik:GridGroupByField FieldName="Group1Name" SortOrder="Ascending" />
                    </GroupByFields>
                </telerik:GridGroupByExpression>
                <telerik:GridGroupByExpression>
                    <SelectFields>
                        <telerik:GridGroupByField Aggregate="First" FieldAlias="Group2NameAlias" FieldName="Group2Name"/>
                        <telerik:GridGroupByField Aggregate="First" FieldAlias="Group2IdAlias" FieldName="Group2Id"/>
                    </SelectFields>
                    <GroupByFields>
                        <telerik:GridGroupByField FieldName="Group2Name" SortOrder="Ascending" />
                    </GroupByFields>
                </telerik:GridGroupByExpression>
            </GroupByExpressions>
            <Columns>
                <telerik:GridBoundColumn UniqueName="ColumnA" DataField="ColumnA" />
                <telerik:GridBoundColumn UniqueName="ColumnB" DataField="ColumnB" />
                ...
                <telerik:GridTemplateColumn UniqueName="link" HeaderText="Link" Groupable="false" SortExpression="sortExpression" HeaderStyle-HorizontalAlign="Left" >
                    <ItemTemplate>
                        <asp:HyperLink ID="itemLink" runat="server"></asp:HyperLink>
                    </ItemTemplate>
                </telerik:GridTemplateColumn>
                    ...
            </Columns>
        </MasterTableView>
    </telerik:RadGrid>


    protected void radGrid1_ItemDataBound(object source, GridItemEventArgs e)
    {
        if (e.Item.ItemType == GridItemType.GroupHeader)
        {
            GridGroupHeaderItem item = (GridGroupHeaderItem)e.Item;
            DataRowView groupDataRow = (DataRowView)e.Item.DataItem;
     
            // Telerik does not allow public access to the GroupLevel property of GridItems.
            // Unfortunately, this is the only way we have found to determine the group level.
            // The GroupIndex is formatted as "Group1_Group2_Group3"
            string[] headerItemGroups = e.Item.GroupIndex.Split('_');
     
            string group1Name;
            string group2Name;
     
            int group1Id;
            int group2Id;
            int headerItemGroupLevel = headerItemGroups.Length - 1; // GroupLevel is 0 based
     
            if (headerItemGroupLevel == 0)
            {
                List<int> expandedGroup1IdList = GetSessionExpandedGroup1IdList();
     
                group1Name = groupDataRow["Group1Name"].ToString();
                group1Id = (int)groupDataRow["Group1Id"];
                     
                // Telerik does not allow access to DataKeyValues in the GridGroupHeaderItems hence the horrible code below.
                // We can add a group by field to the header, grab it on ItemDataBound, and then replace it with meaningful text
                item.DataCell.Text = "Group1: " + group1Name;
                item.Expanded = expandedGroup1IdList.Contains(group1Id);
            }
            else if (headerItemGroupLevel == 1)
            {
                List<int> expandedGroup2IdList = GetSessionExpandedGroup2IdList();
     
                group2Name = groupDataRow["Group2Name"].ToString();
                group2Id = (int)groupDataRow["Group2Id"];
     
                // Telerik does not allow access to DataKeyValues in the GridGroupHeaderItems hence the horrible code below.
                // We can add a group by field to the header, grab it on ItemDataBound, and then replace it with meaningful text
                item.DataCell.Text = "Group2: " + group2Name;
                item.Expanded = expandedGroup2IdList.Contains(group2Id);
            }
        }
        else if (e.Item.ItemType == GridItemType.Item)
        {
            Class1 dataItem= (Class1)e.Item.DataItem;
     
            HyperLink link = (HyperLink)e.Item.FindControl("itemLink");
     
            if (dataItem.property == ...)
            {
                link.NavigateUrl = ...
                link.Text = ...
            }
            else if (dataItem.property == ...)
            {
                link.NavigateUrl = ...
                link.Text = ...
            }
        }
    }
     
    protected void radGrid1_ItemCommand(object source, GridCommandEventArgs e)
    {
        if (e.CommandName == RadGrid.ExpandCollapseCommandName)
        {
            // Telerik does not allow public access to the GroupLevel property of GridItems.
            // Unfortunately, this is the only way we have found to determine the group level.
            // The GroupIndex is formatted as "Group1_Group2_Group3"
            string[] headerItemGroups = e.Item.GroupIndex.Split('_');
            string[] dataItemGroups;
     
            int group1Id;
            int group2Id;
            int headerItemGroupLevel = headerItemGroups.Length - 1; // Group Level is 0 based
     
            bool isExpanded = !e.Item.Expanded; // The item is currently expanding/collapsing so the state is yet to change
     
            foreach (GridDataItem item in e.Item.OwnerTableView.Items)
            {
                dataItemGroups = item.GroupIndex.Split('_');
     
                // Telerik does not provide access to DataKeyValues from GridGroupHeaderItems
                // Loop through all items in the MasterTableView until we find an item that belongs to the group(s) of the clicked item
                // Save the appropriate IDs in a session variable to track which items are expanded
                if (headerItemGroupLevel == 0 && headerItemGroups[0] == dataItemGroups[0])
                {
                    group1Id = (int)item.GetDataKeyValue("Group1Id");
     
                    SaveSessionExpandedGroup1IdList(group1Id, isExpanded);
     
                    break;
                }
                else if (headerItemGroupLevel == 1 && headerItemGroups[0] == dataItemGroups[0] && headerItemGroups[1] == dataItemGroups[1])
                {
                    group2Id = (int)item.GetDataKeyValue("group2Id");
     
                    SaveSessionExpandedGroup2IdList(group2Id, isExpanded);
     
                    break;
                }
            }
        }
    }
  2. Marin
    Admin
    Marin avatar
    1044 posts

    Posted 01 Mar 2012 Link to this post

    Hello Curtis,

     We have already addressed the support ticket opened on the same subject. Please avoid posting duplicate threads since this confuses our support officers. If you do not mind we will continue the communication in the support ticket that was opened.
    For the benefit of the community I am also posting the answer here:

    The ItemDataBound event is fired too late in the grid's life cycle and that's why items that should be shown after expanding are not databound properly and are not visible. A better approach would be traverse the items after the grid is databound, for example in the Page_PreRender event. There you can use the same logic to set which items should be expanded and then rebind the control again. This should also render the child items for each group. 

    protected void Page_PreRender(object sender, EventArgs e)
        {
            var headerItems = RadGrid1.MasterTableView.GetItems(GridItemType.GroupHeader);
            foreach (GridHeaderItem item in headerItems)
            {
                if (item should be expanded)
                {
                    item.Expanded = true;
                }
            }
            RadGrid1.Rebind();
        }

    Kind regards,
    Marin
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Pavel
    Pavel avatar
    13 posts
    Member since:
    Oct 2009

    Posted 12 Apr in reply to Marin Link to this post

    Sorry to be bringing up such and old post back from the dead, but this isn't working for me.

    I am putting the relevant code below, with a few things removed for clarity.

    I can walk through with a debugger, and I know that the .expanded property is getting set correctly, but i can't get it to work.

    <uc1:CommonGrid ID="myGrid" runat="server" EnableEmbeddedSkins="False"
        ShowStatusBar="true"
        AutoGenerateColumns="false"
        ClientSettings-AllowGroupExpandCollapse="true"
        ClientSettings-Selecting-AllowRowSelect="True"
        AllowMultiRowSelection="True"
        AllowAutomaticUpdates="True"
        AllowAutomaticInserts="False"
        AllowAutomaticDeletes="False"
        AutoGenerateEditColumn="False">   
         
        <MasterTableView AutoGenerateColumns="False"
            Summary="Measure Categories"
            DataKeyNames="CategoryId,CategoryName"
            AllowSorting="true"
            AllowNaturalSort="false"
            ShowHeadersWhenNoRecords="True"
            GroupLoadMode="Client"
            CommandItemDisplay="None"
            GroupsDefaultExpanded="false">

    protected void Page_PreRender(object sender, EventArgs e)
    {
        foreach (GridGroupHeaderItem groupHeader in myGrid.MasterTableView.GetItems(GridItemType.GroupHeader))
        {
            var children = groupHeader.GetChildItems();
            var expanded = false;
     
            foreach (GridDataItem child in children)
            {
                if (child.Selected)
                {
                    expanded = true;
                    break;
                }
            }
            groupHeader.Expanded = expanded;
        }
        myGrid.Rebind();
    }

  5. Marin
    Admin
    Marin avatar
    1044 posts

    Posted 15 Apr Link to this post

    Hi,

    When you use GroupLoadMode="Client" the groups are only expanded or collapsed on the client so we recommend to move the logic from Page_PreRender on the client. You can use our client-side API in this case:
    http://docs.telerik.com/devtools/aspnet-ajax/controls/grid/client-side-programming/gridtableview-object/methods/expandgroup

    http://docs.telerik.com/devtools/aspnet-ajax/controls/grid/client-side-programming/gridtableview-object/methods/collapsegroup

    I hope this helps. Let me know if you have any other questions.

    Regards,
    Marin
    Telerik
    Do you need help with upgrading your ASP.NET AJAX, WPF or WinForms projects? Check the Telerik API Analyzer and share your thoughts.
Back to Top