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

[Solved] Difficulty with persistent hierarchal expanded state

6 Answers 98 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Darryl
Top achievements
Rank 1
Darryl asked on 25 Apr 2013, 03:34 PM
Hello,

I have been working with a Hierarchal RadGrid (Latest version), which has a parent and child level (only). I have AJAX enabled, and have an rebind() occurring on an interval defined by an <asp:Timer>. I have wrapped the Grid in a RadAjaxPanel, and the refreshes occur only to the panel when triggered by the Timer.

I believe I have this all setup properly, except that the Child's that are expanded do not persist between AJAX Refreshes triggered by the Timer Rebind(). Any suggestion would be appreciated. General code below:
protected void Timer1_Tick(object sender, EventArgs e)
{
    RadGrid1.Rebind();
}
 
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;
        }
    }
}

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="scomx.PersistentTest.WebForm1" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<%@ Register assembly="Telerik.Web.UI" Namespace="Telerik.Charting" TagPrefix="telerik" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Timer ID="Timer1" runat="server" Interval="15000" OnTick="Timer1_Tick">
    </asp:Timer>
 
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
 
    <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server"
            DefaultLoadingPanelID="RadAjaxLoadingPanel1"
            UpdateInitiatorPanelsOnly="True"
            UpdatePanelsRenderMode="Inline">
            <AjaxSettings>
                <telerik:AjaxSetting AjaxControlID="Timer1">
                    <UpdatedControls>
                        <telerik:AjaxUpdatedControl ControlID="RadGrid1"  />
                    </UpdatedControls>
                </telerik:AjaxSetting>
                <telerik:AjaxSetting AjaxControlID="RadGrid1">
                    <UpdatedControls>
                        <telerik:AjaxUpdatedControl ControlID="RadGrid1" />
                    </UpdatedControls>
                </telerik:AjaxSetting>
            </AjaxSettings>
    </telerik:RadAjaxManager>
 
    <telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" Runat="server" Skin="Default">
    </telerik:RadAjaxLoadingPanel>
 
    <telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server" HorizontalAlign="NotSet" LoadingPanelID="RadAjaxLoadingPanel1">
        <telerik:RadGrid ID="RadGrid1" runat="server" AutoGenerateColumns="false"  Width="100%"
        OnNeedDataSource="List_DataSource"
        OnDetailTableDataBind="Details_DataSource"
        OnDataBound="RadGrid1_DataBound"
        OnItemDataBound="RadGrid1_ItemDataBound">
        <MasterTableView DataKeyNames="Name" Name="Parent">
            <Columns>
                <telerik:GridBoundColumn DataField="Name" HeaderText="Name">
                </telerik:GridBoundColumn>
            </Columns>
            <DetailTables>
                <telerik:GridTableView runat="server" HierarchyLoadMode="ServerOnDemand" AutoGenerateColumns="false" Name="DetailGrid">
                    <Columns>
                        <telerik:GridBoundColumn HeaderText="Alert" DataField="Alert" UniqueName="Detail_Alert" ItemStyle-Width="375px"></telerik:GridBoundColumn>
                        <telerik:GridHyperLinkColumn HeaderText="View Details" DataNavigateUrlFields="Data" UniqueName="Detail_Data" NavigateUrl="http://{0}" Text="Click Here" Target="_blank"></telerik:GridHyperLinkColumn>
                    </Columns>
                </telerik:GridTableView>
            </DetailTables>
        </MasterTableView>
    </telerik:RadGrid>
    </telerik:RadAjaxPanel>
    </div>
    </form>
</body>
</html>

6 Answers, 1 is accepted

Sort by
0
Tsvetoslav
Telerik team
answered on 30 Apr 2013, 12:41 PM
Hi Darryl,

Just remove the RadAjaxPanel. You should not use both RadAjaxManager and RadAjaxPanel togetther. Either one of those must be employed and not both.

All the best, Tsvetoslav
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.
0
Darryl
Top achievements
Rank 1
answered on 30 Apr 2013, 12:47 PM
Thank you for your suggestion.

I did as you suggested, but this did not resolve the problem. Also, I find that the AJAX doesn't work the same without the panel, nor does it show the Loading image when it refreshes now that the Panel has been removed.
0
Vasil
Telerik team
answered on 03 May 2013, 11:47 AM
Hi Darryl,

The approach works in the sample page I just have tested:
<asp:Timer ID="Timer1" runat="server" Interval="2000" OnTick="Timer1_Tick">
</asp:Timer>
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server"
    DefaultLoadingPanelID="RadAjaxLoadingPanel1">
    <AjaxSettings>
        <telerik:AjaxSetting AjaxControlID="Timer1">
            <UpdatedControls>
                <telerik:AjaxUpdatedControl ControlID="RadGrid1" />
            </UpdatedControls>
        </telerik:AjaxSetting>
        <telerik:AjaxSetting AjaxControlID="RadGrid1">
            <UpdatedControls>
                <telerik:AjaxUpdatedControl ControlID="RadGrid1" />
            </UpdatedControls>
        </telerik:AjaxSetting>
    </AjaxSettings>
</telerik:RadAjaxManager>
 
<telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" Skin="Default">
</telerik:RadAjaxLoadingPanel>
 
<telerik:RadGrid ID="RadGrid1" runat="server" AutoGenerateColumns="false" Width="100%"
    OnNeedDataSource="RadGrid1_NeedDataSource">
    <MasterTableView >
        <Columns>
            <telerik:GridTemplateColumn>
                <ItemTemplate>
                    <%# DateTime.Now()%>
                </ItemTemplate>
            </telerik:GridTemplateColumn>
        </Columns>
    </MasterTableView>
</telerik:RadGrid>

Protected Sub RadGrid1_NeedDataSource(sender As Object, e As GridNeedDataSourceEventArgs)
    RadGrid1.DataSource = New Integer() {1, 2, 3}
End Sub
 
Protected Sub Timer1_Tick(sender As Object, e As EventArgs)
    RadGrid1.Rebind()
End Sub

Try to set UpdateInitiatorPanelsOnly="false" to see if there is any difference.

Kind regards,
Vasil
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.
0
Darryl
Top achievements
Rank 1
answered on 03 May 2013, 01:45 PM
As I understand it, the sample you provided isn't for a hierarchal grid. My problem is the hierarchy's expansion is not persisting. I simply want to persist the fact that I expanded one of the children. So when it auto-refreshes at 1 minute, it doesn't close my expanded DetailsTable.

Thanks for looking into this!
0
Vasil
Telerik team
answered on 08 May 2013, 10:32 AM
Hello Darryl,

I am attaching here an example with hierarchy grid that is persisting its expanded items when timer is used in the page.

Greetings,
Vasil
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.
0
Darryl
Top achievements
Rank 1
answered on 08 May 2013, 12:01 PM
Thanks for your help,

I had been making a series of changes, and eventually got it to work. I do realize that part of my problem was the OnItemCommand was not triggering.

Once this was resolved, it seems it is working perfectly.

Thanks again.
Tags
Grid
Asked by
Darryl
Top achievements
Rank 1
Answers by
Tsvetoslav
Telerik team
Darryl
Top achievements
Rank 1
Vasil
Telerik team
Share this question
or