This is a migrated thread and some comments may be shown as answers.

How to maintain expanded rows of "DetailTable" after postback

4 Answers 923 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Nirav
Top achievements
Rank 1
Nirav asked on 22 Aug 2011, 03:47 PM
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,



4 Answers, 1 is accepted

Sort by
0
Nirav
Top achievements
Rank 1
answered on 19 Sep 2011, 03:49 PM
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
0
Ana
Top achievements
Rank 1
answered on 20 Jul 2012, 04:17 PM
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
0
Shinu
Top achievements
Rank 2
answered on 23 Jul 2012, 05:14 AM
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.
0
Sam
Top achievements
Rank 1
answered on 13 Aug 2012, 08:51 AM

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

 

Tags
Grid
Asked by
Nirav
Top achievements
Rank 1
Answers by
Nirav
Top achievements
Rank 1
Ana
Top achievements
Rank 1
Shinu
Top achievements
Rank 2
Sam
Top achievements
Rank 1
Share this question
or