How to maintain expanded rows of "DetailTable" after postback

5 posts, 0 answers
  1. Nirav
    Nirav avatar
    48 posts
    Member since:
    Sep 2008

    Posted 22 Aug 2011 Link to this post

    Hi,
    I am using Telerik controls version "2009.3.1103.20", visual studio 2008 and website project.
    Now on one of my page, I have RadGrid and have "DetailTable" underneath "MasterTableView", so basically when I assign datasource to my master table, it displays option to "Expand\Collapse" and when I click on "Expand" arrow, it fires "OnDetailTableDataBind" event where I assign dataset to my detail table and it displays whatever number of rows I have in detail table.
    So basically I have kind of master-detail view where I can expand\collapse items to view detail view.

    Now on my "DetailTable", I have some rows which has some buttons and on click of those buttons, I am updating some values in my database and refreshing grid. The problem is that while binding grid again, grid is losing its state of already expanded rows and all the rows are in "Collapsed" state. What I want is after rebinding grid, it should keep expanded rows as it is. This is happening on postback always. Even If I use "Sorting" on my master table fields, it collapses all the rows but I want to show the expanded rows as it is whichever were expanded already by user, should stay expanded after postback.

    Any suggestion how to achieve this?
    Here is my RadGrid.
    <telerik:RadGrid ID="RadGrid1" runat="server" AllowPaging="true" AllowSorting="true"
        AutoGenerateColumns="False" GridLines="Both" OnNeedDataSource="RadGrid1_needdatasource"
        OnItemDataBound="RadGrid1_ItemDataBound" OnDetailTableDataBind="RadGrid1_DetailTableDataBind"
        OnItemCreated="RadGrid1_ItemCreated" AllowMultiRowSelection="true"
        AllowFilteringByColumn="true" OnItemCommand="RadGrid1_ItemCommand"
          
                                                  
        SelectedItemStyle-CssClass="SelectedItem" Skin="Default">
        <PagerStyle Mode="NextPrevNumericAndAdvanced" Position="TopAndBottom" AlwaysVisible="true" />
        <ClientSettings EnableRowHoverStyle="true" EnablePostBackOnRowClick="true">
            <Selecting AllowRowSelect="true" />
        </ClientSettings>
        <FooterStyle BackColor="LightBlue" />
        <MasterTableView ShowHeadersWhenNoRecords="true" AllowFilteringByColumn="true" DataKeyNames="RequestInfoID"
            Name="ApprovalsMaster">
            <DetailTables>
                <telerik:GridTableView DataKeyNames="RequestInfoID" Width="80%" Name="ApprovalsDetail"
                    AllowPaging="false" runat="server">
                    <ParentTableRelation>
                        <telerik:GridRelationFields DetailKeyField="RequestInfoID" MasterKeyField="RequestInfoID" />
                    </ParentTableRelation>
                    <Columns>
                        <telerik:GridBoundColumn SortExpression="ApprovalLevelID" HeaderText="ApprovalLevelID"
                            HeaderButtonType="TextButton" DataField="ApprovalLevelID" UniqueName="ApprovalLevelID">
                        </telerik:GridBoundColumn>
                        <telerik:GridTemplateColumn HeaderText="Approve" UniqueName="ApproveRequest" AllowFiltering="false">
                            <ItemTemplate>
                                <asp:Button runat="server" ID="btnApproveRequest" Text="Approve" CssClass="ButtonCSS"
                                    ToolTip="Click here to Approve Request" CausesValidation="False" OnClick="btnApproveRequest_Click"
                                    OnClientClick="javascript:var agree= confirm('Are you sure you want to approve this Request? '); if(agree){ Page_BlockSubmit = false;buttonClicked_WithObj(this); return true; };else {return false;};"
                                    CommandArgument='<%# 
                                Eval ( "RequestInfoID").ToString() 
                                + ";" +
                                Eval ( "ApprovalLevelID").ToString() 
                                  
                                %>' />
                                  
                            </ItemTemplate>
                        </telerik:GridTemplateColumn>
                    </Columns>
                </telerik:GridTableView>
            </DetailTables>
            <Columns>
                <telerik:GridNumericColumn DataField="RequestInfoID" HeaderText="Request No." SortExpression="RequestInfoID"
                    DataType="System.Int64" FilterControlWidth="40px">
                </telerik:GridNumericColumn>
                <telerik:GridBoundColumn DataField="DepartmentName" HeaderText="Department" SortExpression="DepartmentName"
                    UniqueName="DepartmentName">
                </telerik:GridBoundColumn>
            </Columns>
            <EditFormSettings>
                <PopUpSettings ScrollBars="None" />
            </EditFormSettings>
            <ExpandCollapseColumn Resizable="False" Visible="False">
                <HeaderStyle />
            </ExpandCollapseColumn>
            <RowIndicatorColumn Visible="False">
                <HeaderStyle />
            </RowIndicatorColumn>
        </MasterTableView>
    </telerik:RadGrid>

    Here is what I tried to expand it back after postback but could not get it working, not sure why. Just pasting for reference which I tried. Please do let me know the best option to achieve this.
    OnDataBound="RadGrid1_DataBound"
    OnDataBinding="RadGrid1_DataBinding"                                  
      
        protected void RadGrid1_DataBound(object sender, EventArgs e)
        {
            LoadGroupsExpandedState(RadGrid1);
        }
      
        protected void RadGrid1_DataBinding(object sender, EventArgs e)
        {
            SaveGroupsExpandedState(RadGrid1);
        }  
      
        private void SaveGroupsExpandedState(RadGrid grid)
        {
      
            GridItem[] groupItems = grid.MasterTableView.GetItems(GridItemType.GroupHeader);
            if (groupItems.Length > 0)
            {
                List<string> collapsedIndexes = new List<string>();
                foreach (GridItem item in groupItems)
                {
                    if (!item.Expanded)
                    {
                        GridGroupHeaderItem groupHeader = (GridGroupHeaderItem)item;
                        collapsedIndexes.Add(groupHeader.DataCell.Text);
                    }
                }
      
                Session["groupExpandedState"] = collapsedIndexes;
            }
        }
      
        private void LoadGroupsExpandedState(RadGrid grid)
        {
            List<string> collapsedIndexes = Session["groupExpandedState"] as List<string>;
            if (collapsedIndexes != null)
            {
                foreach (GridItem item in grid.MasterTableView.GetItems(GridItemType.GroupHeader))
                {
                    GridGroupHeaderItem groupHeader = (GridGroupHeaderItem)item;
                    if (collapsedIndexes.Contains(groupHeader.DataCell.Text))
                    {
                        item.Expanded = false;
                    }
                }
            }
        }

    Thanks in advance,



  2. Nirav
    Nirav avatar
    48 posts
    Member since:
    Sep 2008

    Posted 19 Sep 2011 Link to this post

    Hi Admin,

    Can someone help me for this issue please?
    I just need to maintain collapsed items after postback when one of the button on mastertable is pressed.

    Thanks,
    Nirav Parekh
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Ana
    Ana avatar
    4 posts
    Member since:
    Mar 2011

    Posted 20 Jul 2012 Link to this post

    Nirav,

    I am looking for solution for the similar behaviour  but in ajaxified radgrid. Did you figure out the solution for it? If so, could you please share it here.

    Also, can some one please provide a solution on how to do this.

    p.s: telerik version I am using is 2011.1.519.35

    Thank in advance,
    Ana
  5. Shinu
    Shinu avatar
    17764 posts
    Member since:
    Mar 2007

    Posted 23 Jul 2012 Link to this post

    Hi Ana,

    Please take a look into the following code snippet to retain expanded/selected state in hierarchy on rebind.

    ASPX:
    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
        <AjaxSettings>
            <telerik:AjaxSetting AjaxControlID="RadGrid1">
                <UpdatedControls>
                    <telerik:AjaxUpdatedControl ControlID="RadGrid1" LoadingPanelID="RadAjaxLoadingPanel1" />
                </UpdatedControls>
            </telerik:AjaxSetting>
        </AjaxSettings>
    </telerik:RadAjaxManager>
    <asp:Button ID="grdRebind" runat="server" Text="Rebind grid" OnClick="grdRebind_Click" />
    <telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" />
    <telerik:RadGrid ID="RadGrid1" DataSourceID="SqlDataSource1" runat="server"
         AutoGenerateColumns="False" AllowSorting="True" AllowMultiRowSelection="true"
         OnDataBound="RadGrid1_DataBound" OnItemCommand="RadGrid1_ItemCommand">
        <MasterTableView DataSourceID="SqlDataSource1" DataKeyNames="CustomerID" CommandItemDisplay="Top">
            <DetailTables>
                <telerik:GridTableView DataKeyNames="OrderID" DataSourceID="SqlDataSource2"
                    runat="server" CommandItemDisplay="Top">
                    <ParentTableRelation>
                        <telerik:GridRelationFields DetailKeyField="CustomerID" MasterKeyField="CustomerID" />
                    </ParentTableRelation>
                    <DetailTables>
                        <telerik:GridTableView DataKeyNames="OrderID" DataSourceID="SqlDataSource3"
                            runat="server" CommandItemDisplay="Top">
                            <ParentTableRelation>
                                <telerik:GridRelationFields DetailKeyField="OrderID" MasterKeyField="OrderID" />
                            </ParentTableRelation>
                            <Columns>
                                <telerik:GridBoundColumn SortExpression="UnitPrice" HeaderText="Unit Price" HeaderButtonType="TextButton"
                                    DataField="UnitPrice" UniqueName="UnitPrice">
                                </telerik:GridBoundColumn>
                                <telerik:GridBoundColumn SortExpression="Quantity" HeaderText="Quantity" HeaderButtonType="TextButton"
                                    DataField="Quantity" UniqueName="Quantity">
                                </telerik:GridBoundColumn>
                                <telerik:GridButtonColumn UniqueName="OrderDetailsSelectColumn" CommandName="Select"
                                    Text="Select" />
                                <telerik:GridButtonColumn UniqueName="OrderDetailsDeselectColumn" CommandName="Deselect"
                                    Text="Deselect" />
                            </Columns>
                        </telerik:GridTableView>
                    </DetailTables>
                    <Columns>
                        <telerik:GridBoundColumn SortExpression="OrderID" HeaderText="OrderID" HeaderButtonType="TextButton"
                            DataField="OrderID" UniqueName="OrderID">
                        </telerik:GridBoundColumn>
                        <telerik:GridBoundColumn SortExpression="EmployeeID" HeaderText="EmployeeID" HeaderButtonType="TextButton"
                            DataField="EmployeeID" UniqueName="EmployeeID">
                        </telerik:GridBoundColumn>
                        <telerik:GridButtonColumn UniqueName="OrdersSelectColumn" CommandName="Select" Text="Select" />
                        <telerik:GridButtonColumn UniqueName="OrdersDeselectColumn" CommandName="Deselect"
                            Text="Deselect" />
                    </Columns>
                </telerik:GridTableView>
            </DetailTables>
            <Columns>
                <telerik:GridBoundColumn SortExpression="CustomerID" HeaderText="CustomerID" HeaderButtonType="TextButton"
                    DataField="CustomerID" UniqueName="CustomerID">
                </telerik:GridBoundColumn>
                <telerik:GridBoundColumn SortExpression="ContactName" HeaderText="Contact Name" HeaderButtonType="TextButton"
                    DataField="ContactName" UniqueName="ContactName">
                </telerik:GridBoundColumn>
                <telerik:GridButtonColumn UniqueName="CustomersSelectColumn" CommandName="Select"
                    Text="Select" />
                <telerik:GridButtonColumn UniqueName="CustomersSelectColumn" CommandName="Deselect"
                    Text="Deselect" />
            </Columns>
        </MasterTableView>
    </telerik:RadGrid>

    C#:
    private Hashtable _ordersExpandedState;
    private Hashtable _selectedState;
     
    public void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //reset states
            this._ordersExpandedState = null;
            this.Session["_ordersExpandedState"] = null;
            this._selectedState = null;
            this.Session["_selectedState"] = null;
        }
    }
    //Save/load expanded states Hash from the session
    //this can also be implemented in the ViewState
    private Hashtable ExpandedStates
    {
        get
        {
            if (this._ordersExpandedState == null)
            {
                _ordersExpandedState = this.Session["_ordersExpandedState"] as Hashtable;
                if (_ordersExpandedState == null)
                {
                    _ordersExpandedState = new Hashtable();
                    this.Session["_ordersExpandedState"] = _ordersExpandedState;
                }
            }
     
            return this._ordersExpandedState;
        }
    }
     
    //Clear the state for all expanded children if a parent item is collapsed
    private void ClearExpandedChildren(string parentHierarchicalIndex)
    {
        string[] indexes = new string[this.ExpandedStates.Keys.Count];
        this.ExpandedStates.Keys.CopyTo(indexes, 0);
        foreach (string index in indexes)
        {
            //all indexes of child items
            if (index.StartsWith(parentHierarchicalIndex + "_") ||
                index.StartsWith(parentHierarchicalIndex + ":"))
            {
                this.ExpandedStates.Remove(index);
            }
        }
    }
     
    private void ClearSelectedChildren(string parentHierarchicalIndex)
    {
        string[] indexes = new string[this.SelectedStates.Keys.Count];
        this.SelectedStates.Keys.CopyTo(indexes, 0);
        foreach (string index in indexes)
        {
            //all indexes of child items
            if (index.StartsWith(parentHierarchicalIndex + "_") ||
                index.StartsWith(parentHierarchicalIndex + ":"))
            {
                this.SelectedStates.Remove(index);
            }
        }
    }
     
    //Save/load selected states Hash from the session
    //this can also be implemented in the ViewState
    private Hashtable SelectedStates
    {
        get
        {
            if (this._selectedState == null)
            {
                _selectedState = this.Session["_selectedState"] as Hashtable;
                if (_selectedState == null)
                {
                    _selectedState = new Hashtable();
                    this.Session["_selectedState"] = _selectedState;
                }
            }
     
            return this._selectedState;
        }
    }
    protected void RadGrid1_ItemCommand(object source, GridCommandEventArgs e)
    {
        //save the expanded/selected state in the session
        if (e.CommandName == RadGrid.ExpandCollapseCommandName)
        {
            //Is the item about to be expanded or collapsed
            if (!e.Item.Expanded)
            {
                //Save its unique index among all the items in the hierarchy
                this.ExpandedStates[e.Item.ItemIndexHierarchical] = true;
            }
            else //collapsed
            {
                this.ExpandedStates.Remove(e.Item.ItemIndexHierarchical);
                this.ClearSelectedChildren(e.Item.ItemIndexHierarchical);
                this.ClearExpandedChildren(e.Item.ItemIndexHierarchical);
            }
        }
        //Is the item about to be selected
        else if (e.CommandName == RadGrid.SelectCommandName)
        {
            //Save its unique index among all the items in the hierarchy
            this.SelectedStates[e.Item.ItemIndexHierarchical] = true;
        }
        //Is the item about to be deselected
        else if (e.CommandName == RadGrid.DeselectCommandName)
        {
            this.SelectedStates.Remove(e.Item.ItemIndexHierarchical);
        }
    }
    protected void RadGrid1_DataBound(object sender, EventArgs e)
    {
        //Expand all items using our custom storage
        string[] indexes = new string[this.ExpandedStates.Keys.Count];
        this.ExpandedStates.Keys.CopyTo(indexes, 0);
     
        ArrayList arr = new ArrayList(indexes);
        //Sort so we can guarantee that a parent item is expanded before any of
        //its children
        arr.Sort();
     
        foreach (string key in arr)
        {
            bool value = (bool)this.ExpandedStates[key];
            if (value)
            {
                RadGrid1.Items[key].Expanded = true;
            }
        }
     
        //Select all items using our custom storage
        indexes = new string[this.SelectedStates.Keys.Count];
        this.SelectedStates.Keys.CopyTo(indexes, 0);
     
        arr = new ArrayList(indexes);
        //Sort to ensure that a parent item is selected before any of its children
        arr.Sort();
     
        foreach (string key in arr)
        {
            bool value = (bool)this.SelectedStates[key];
            if (value)
            {
                RadGrid1.Items[key].Selected = true;
            }
        }
    }
    protected void grdRebind_Click(object sender, EventArgs e)
    {
        RadGrid1.Rebind();
    }


    Please check this code library for more details.

    Thanks,
    Shinu.
  6. Sam
    Sam avatar
    1 posts
    Member since:
    Feb 2011

    Posted 13 Aug 2012 Link to this post

    It sounds as if you are rebinding the grid in the code page everytime it loads. you can obviously use ajaxing as stated in the post before but if i am correct a more simple fix would be to only bind the grid if it is not a postback:

     

    if(!IsPostBack)
    {
        RadGrid.DataSource = Data;
        RadGrid.DataBind();
    }

     

    Hope this helps

    Sam

     

Back to Top
UI for ASP.NET Ajax is Ready for VS 2017