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

Programmatically expand/collapse RadTreeList item when load on demand is activated.

11 Answers 604 Views
TreeList
This is a migrated thread and some comments may be shown as answers.
Jerome MAILLEY
Top achievements
Rank 1
Jerome MAILLEY asked on 10 Jan 2018, 10:00 AM

Hi,

In a web application, I use your RadTreeList to display some hierarchical data. Because the amount of data can be large, I set the AllowLoadOnDemand to true and created an OnChildItemsDataBind event handler. The load on demand mechanism works perfectly. 

The RadTreeList contains a various number of column which are dynamically created but the first column is a TreeListSelectColumn which statically created. This allows user to check/unckeck some items in the TreeList and the result (checked items) must be saved in a database. Obviously, when the user reach the TreeList later, the state of the checkboxes must be restored.

Because TreeList items check state must be restored at the TreeList initialisation and the amount of TreeList data can be huge, I am looking for a way to expand all parent items of these checked items.

As an example let's consider this simple TreeList structure :

- Item1

    |_ Item11

        |_ Item111

        |_ Item112

    |_ Item12

        |_ Item121

    |_ Item13

- Item2

    |_ Item21

        |_ Item211
    |_ Item22

If user checked "Item211" and saved his changes, I'd like the TreeList to be initialised like this :

- Item1             (collapsed because no child item are checked)
- Item2             (expanded because a child item is checked)
    |_ Item21     (same here)
        |_ Item211
    |_ Item22

I cannot find a way to achieve this with load on demand feature. The reason is quite simple: the load on demand pattern requires to load only the root elements on TreeList_NeedDataSource event and then gradually child element on TreeList_ChildItemsDataBind event. In my previous example, this means that at page load the TreeList contains only 2 items (Item1 and Item2) so their child cannot be expanded because they does not exists.

However that feature, for me, seems to be very important. When a tree contains a lot of data, user must have a way to access easily to his previous selection without expanding manually all the parent nodes. Also, this feature seems to be necessary if I want to implement a seach feature.

Could you help me ?

Thanks,

 

11 Answers, 1 is accepted

Sort by
0
Eyup
Telerik team
answered on 15 Jan 2018, 08:29 AM
Hello Jerome,

I am afraid this requirement is not supported with LoadOnDemand because the inner items are not created at all. Actually, this is the point of load-on-demand generation - to skip loading and creating any items when they are not visible to the user.

Nevertheless, you can check recursive selection provided by RadTreeList:
https://demos.telerik.com/aspnet-ajax/treelist/examples/selecting/serversideselection/defaultcs.aspx

And the ExpandToLevel method:
https://docs.telerik.com/devtools/aspnet-ajax/controls/treelist/items/expand-collapse-items

Regards,
Eyup
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 15 Jan 2018, 10:53 AM

Hi,

Thanks for your answer,

Are you meaning that a search feature on RadTreeList with load-on-demand is unthinkable because it's not possible to expand/collapse node on server side ?

0
Eyup
Telerik team
answered on 18 Jan 2018, 08:13 AM
Hi Jerome,

Yes, you are correct. This is due to the fact it is not possible to access and traverse the inner items when load on demand is enabled.

Regards,
Eyup
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 18 Jan 2018, 09:53 AM

Hi Eyup,

Thanks for your answer. 

Do you have any suggestion for me to get what I need with another telerik control ?

My needs are :

- Hierarchical display of the same objects

- Selection with checkbox

- Search feature

- Load on demand because of big volume of data

- Dynamic creation of columns

 

Here is the structure of my usercontrol :

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="HierarchicalComboBoxView.ascx.cs" Inherits="AS.Cpm.Web.Site.WebReportGenerator.Views.HierarchicalComboBoxView" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
 
<div id="DimensionLabelBg">
    <asp:Label ID="Label" runat="server" CssClass="labelComboBox"></asp:Label></div>
<telerik:RadDropDownTree ID="RadDropDownTree" runat="server" EnableViewState="false" CheckBoxes="SingleCheck" OnNodeDataBound="RadDropDownTree_NodeDataBound" OnDataBound="RadDropDownTree_DataBound"
    DataFieldID="NodeId" DataFieldParentID="ParentId" DataTextField="Text" DataValueField="Value"
    Width="90%" RenderMode="Lightweight" Skin="Metro">
</telerik:RadDropDownTree>
<telerik:RadButton ID="BtnExtendedView" runat="server" Width="8%">
    <Icon PrimaryIconCssClass="rbEdit" />
</telerik:RadButton>
<telerik:RadWindow ID="ExtentedViewWindow" runat="server" MinWidth="600" MinHeight="400" MaxHeight="500" DestroyOnClose="true">
    <ContentTemplate>
        <telerik:RadPageLayout runat="server" GridType="Fluid" ShowGrid="false" HtmlTag="None">
            <telerik:LayoutRow RowType="Container">
                <Rows>
                    <telerik:LayoutRow>
                        <Content>
                            <div class="treeSearch rddtHeader" style="width: 100%; height: 30px; background: #8d7d74">
                                <span style="font-weight: bold; margin-left: 2%">Code</span>
                                <span>- </span>
                                <span style="font-style: italic;">Label</span>
                            </div>
                            <telerik:RadTreeList ID="WindowGrid" runat="server" AllowPaging="false" RenderMode="Lightweight"
                                Skin="Metro" DataKeyNames="NodeId" ParentDataKeyNames="ParentId" ClientDataKeyNames="Value"
                                AllowSorting="false" AllowFilteringByColumn="false" GridLines="None" OnNeedDataSource="WindowGrid_NeedDataSource"
                                AutoGenerateColumns="false" AllowMultiRowSelection="false" ExpandCollapseMode="Client">
                                <Columns>
                                    <telerik:TreeListSelectColumn HeaderStyle-Width="20" />
                                </Columns>
                                <ClientSettings>
                                    <Selecting AllowItemSelection="true" />
                                    <Scrolling AllowScroll="True" UseStaticHeaders="True" SaveScrollPosition="true" />
                                </ClientSettings>
                            </telerik:RadTreeList>
                        </Content>
                    </telerik:LayoutRow>
                    <telerik:LayoutRow Height="30" WrapperHtmlTag="Div" WrapperCssClass="extended-window-buttons-container">
                        <Content>
                            <telerik:RadButton runat="server" ID="RadWindowCancelButton" />
                            <telerik:RadButton runat="server" ID="RadWindowOkButton" />
                        </Content>
                    </telerik:LayoutRow>
                </Rows>
            </telerik:LayoutRow>
        </telerik:RadPageLayout>
    </ContentTemplate>
</telerik:RadWindow>

 

WindowGrid (RadTreeList) and RadDropDownTree display exactly the same data. One was made for quick selection, the other one for a more comfortable selection). Only the number of column is different (RadTreeList is in a Window which allows to display more column than RadDropDownTree).

Because RadTreeList exposes the same data that RadDropDownTree, if the number of data is huge, the rendered html page contains to two time this number of data. These UserControl (HierarchicalComboBoxView) are created dynamically in a RadAjaxPanel, and the number may vary from 1 to 25. I let you imagine if I have 25 HierarchicalComboBoxView with 50000 data on each, the size of the result page. This often cause ASP timeout.

I hope you will help me to deal with these issue,

Thanks,

0
Eyup
Telerik team
answered on 19 Jan 2018, 12:10 PM
Hello Jerome,

The closes control resembling your description is RadGrid, but it does not support self-hierarchy:
https://demos.telerik.com/aspnet-ajax/grid/examples/data-binding/programmatic-hierarchy/defaultcs.aspx

You can try using RadTreeList in combination with RadFilter:
https://demos.telerik.com/aspnet-ajax/treelist/examples/integration/filteringwithradfilter/defaultcs.aspx?product=filter

Regards,
Eyup
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 24 Jan 2018, 10:29 AM

Hi Eyup,

Thanks for your suggestion, I will consider it ASAP

It seems that I have found another issue. Here is my code :

<telerik:RadTreeList ID="WindowDynamicGrid" runat="server" AllowPaging="false" RenderMode="Lightweight"
    Skin="Metro" DataKeyNames="NodeId" ParentDataKeyNames="ParentId" ClientDataKeyNames="Value" Width="800px"
    AllowSorting="false" AllowFilteringByColumn="false" GridLines="None" OnNeedDataSource="WindowGrid_NeedDataSource"
    AutoGenerateColumns="false" AllowMultiRowSelection="false" ExpandCollapseMode="Client" OnItemCreated="WindowDynamicGrid_ItemCreated">
    <Columns>
        <telerik:TreeListSelectColumn HeaderStyle-Width="20" visible="true" />
    </Columns>
    <ClientSettings>
        <ClientEvents OnTreeListCreated="OnTreeListCreated" OnItemSelected="OnItemSelected"/>
        <Selecting AllowItemSelection="true" />
        <Scrolling AllowScroll="True" UseStaticHeaders="True" SaveScrollPosition="true" />
    </ClientSettings>
</telerik:RadTreeList>

 

protected void WindowDynamicGrid_ItemCreated(object sender, TreeListItemCreatedEventArgs e)
{
    var item = e.Item as TreeListDataItem;
    if (item != null)
    {
        Control checkbox = item.FindControl("columnSelectCheckBox");
        var comboBoxItem = item.DataItem as HierarchicalComboBoxItem;
        if (comboBoxItem != null)
        {
            item.Expanded = true;
            item.Selected = comboBoxItem.Checked;
            if(checkbox != null)
                ((CheckBox)checkbox).Visible = comboBoxItem.Checkable;
        }
    }
}

 

As you can see, the WindowDynamicGrid_ItemCreated handler set item.Expanded to true for each item of the RadTreeList. However, the items are all collapsed when I execute my code as you can see on my attached screenshot.

Thanks,

0
Eyup
Telerik team
answered on 26 Jan 2018, 01:47 PM
Hello,

The RadTreeList has special methods to achieve this requirement. Expanding the items one by one won't work for the inner levels and you can use the specially designated methods to do that:
https://docs.telerik.com/devtools/aspnet-ajax/controls/treelist/items/expand-collapse-items

Regards,
Eyup
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 29 Jan 2018, 05:10 PM

Hi Eyup,

Thanks for your answer,

It was a bit tricky because of RadTreeList binding behaviour, but It seems that I finaly fixed my issue by using ClientExpandedIndexes as follow:

protected void WindowDynamicGrid_ItemDataBound(object sender, TreeListItemDataBoundEventArgs e)
{
    var radTreeList = sender as RadTreeList;
    var item = e.Item as TreeListDataItem;
    if (item != null)
    {
        var comboBoxItem = item.DataItem as HierarchicalComboBoxItem;
        if (comboBoxItem != null && comboBoxItem.Expanded)
        {
            radTreeList.ClientExpandedIndexes.Add(item.HierarchyIndex);
        }
    }
}

 

Thanks again,

 

0
Eyup
Telerik team
answered on 30 Jan 2018, 08:10 AM
Hi Jerome,

Thank you for sharing your specific solution with our community.
Please feel free to turn to us if new questions arise.

Regards,
Eyup
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Jerome MAILLEY
Top achievements
Rank 1
answered on 30 Jan 2018, 01:49 PM

Hi Eyup,

Please consider the following code which is a big summary of how my web application is built.

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TelerikTreeListGhostColumnIssue.Default" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
 
<!DOCTYPE html>
 
<head runat="server">
    <title>Telerik issue</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager runat="server" ID="scriptManager" EnablePartialRendering="true" AllowCustomErrorsRedirect="false">
        </asp:ScriptManager>
        <div>
            <telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server">
                <asp:PlaceHolder ID="DimensionsHolder" runat="server"></asp:PlaceHolder>
            </telerik:RadAjaxPanel>
            <asp:Button ID="CustomButton" runat="server" Text="Click here" OnClick="CustomButton_Click" />
        </div>
    </form>
</body>
</html>

 

Default.aspx.cs :

namespace TelerikTreeListGhostColumnIssue
{
    public partial class Default : System.Web.UI.Page
    {
 
        protected void Page_Load(object sender, EventArgs e)
        {
            if(!IsPostBack)
                AddTreeListControl();
        }
 
        protected void CustomButton_Click(object sender, EventArgs e)
        {
            DimensionsHolder.Controls.Clear();
            AddTreeListControl();
        }
 
        private void AddTreeListControl()
        {
            TreeListControl treeListControl = (TreeListControl)new UserControl().LoadControl("~/TreeListControl.ascx");
            DimensionsHolder.Controls.Add(treeListControl);
        }
    }
}

 

TreeListControl.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TreeListControl.ascx.cs" Inherits="TelerikTreeListGhostColumnIssue.TreeListControl" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
 
<telerik:RadTreeList ID="WindowGrid" runat="server" AllowPaging="false" RenderMode="Lightweight"
        DataKeyNames="NodeId" ParentDataKeyNames="ParentId"
        AllowSorting="false" AllowFilteringByColumn="false" GridLines="None" OnNeedDataSource="WindowGrid_NeedDataSource"
        AutoGenerateColumns="false" AllowMultiRowSelection="false" ExpandCollapseMode="Client">
        <Columns>
            <telerik:TreeListSelectColumn HeaderStyle-Width="20" />
        </Columns>
</telerik:RadTreeList>

 

TreeListControl.ascx.cs

namespace TelerikTreeListGhostColumnIssue
{
    public partial class TreeListControl : System.Web.UI.UserControl
    {
        public List<CategoryItem> CategoryItems = new List<CategoryItem>()
        {
            new CategoryItem(1, 0, "R4", "this is a root", "plus"),
            new CategoryItem(2, 1, "R1", "child 1", "minus"),
            new CategoryItem(3, 1, "R2", "child 2", "minus"),
            new CategoryItem(4, 0, "R4i", "this is a root", "plus"),
            new CategoryItem(5, 0, "L200", "this is a root", "minus"),
            new CategoryItem(6, 5, "L100", "child 1", "plus"),
            new CategoryItem(7, 5, "L101", "child 2", "minus"),
            new CategoryItem(8, 5, "L102", "child 3", "plus"),
            new CategoryItem(9, 5, "L103", "child 4", "minus"),
        };
 
        protected void Page_Init(object sender, EventArgs e)
        {
            List<ComboBoxColumn> columns = GetExtendedViewColumns();
            foreach (var column in columns)
                WindowGrid.Columns.Add(GetGridColumnFromComboBoxColumn(column));
        }
 
        protected void WindowGrid_NeedDataSource(object sender, Telerik.Web.UI.TreeListNeedDataSourceEventArgs e)
        {
            WindowGrid.DataSource = CategoryItems;
        }
 
        protected List<ComboBoxColumn> GetExtendedViewColumns()
        {
            var columns = new List<ComboBoxColumn>();
            columns.Add(new ComboBoxColumn() { Title = "Code", ColumnType = ComboBoxColumn.CBColumnType.Text, DataPropertyName = "Code" });
            columns.Add(new ComboBoxColumn() { Title = "Label", ColumnType = ComboBoxColumn.CBColumnType.Text, DataPropertyName = "Label" });
            columns.Add(new ComboBoxColumn() { Title = "Sign", ColumnType = ComboBoxColumn.CBColumnType.Text, DataPropertyName = "Sign" });
            return columns;
        }
 
        private TreeListEditableColumn GetGridColumnFromComboBoxColumn(ComboBoxColumn column)
        {
            switch (column.ColumnType)
            {
                case CBColumnType.Text:
                    var gridBoundColumn = new TreeListBoundColumn();
                    gridBoundColumn.DataField = column.DataPropertyName;
                    gridBoundColumn.HeaderStyle.Width = new System.Web.UI.WebControls.Unit(150);
                    gridBoundColumn.HeaderText = column.Title;
                    return gridBoundColumn;
                case CBColumnType.Checkbox:
                    var gridCheckBoxColumn = new TreeListCheckBoxColumn();
                    gridCheckBoxColumn.DataField = column.DataPropertyName;
                    gridCheckBoxColumn.HeaderStyle.Width = new System.Web.UI.WebControls.Unit(100);
                    gridCheckBoxColumn.HeaderText = column.Title;
                    return gridCheckBoxColumn;
                default:
                    throw new NotImplementedException();
            }
        }
    }
}

 

ComboBoxColumn.cs

namespace TelerikTreeListGhostColumnIssue.Code
{
    public class ComboBoxColumn
    {
        /// <summary> Title </summary>
        public string Title { get; set; }
 
        /// <summary> DataPropertyName </summary>
        public string DataPropertyName { get; set; }
 
        /// <summary> ColumnType </summary>
        public CBColumnType ColumnType { get; set; }
 
        /// <summary> ComboBox column types </summary>
        public enum CBColumnType
        {
            Text,
            Checkbox
        }
    }
}

 

CategoryItem.cs

namespace TelerikTreeListGhostColumnIssue.Code
{
    public class CategoryItem
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CategoryItem"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        public CategoryItem(int nodeId, int parentId, string code, string label, string sign)
        {
            this.NodeId = nodeId;
            this.ParentId = parentId;
            this.Code = code;
            this.Label = label;
            this.Sign = sign;
        }
 
        /// <summary> NodeId. </summary>
        public int NodeId { get; set; }
 
        /// <summary> ParentId. </summary>
        public int ParentId { get; set; }
 
        /// <summary> Code. </summary>
        public string Code { get; set; }
 
        //// <summary> Label. </summary>
        public string Label { get; set; }
 
        /// <summary> Sign. </summary>
        public string Sign { get; set; }
 
        /// <summary> Value. </summary>
        public string Value { get; set; }
    }
}

 

The point is : each time you are clicking on the "Click here" button, you will notice that some empty columns are added in the RadTreeList. And this, even if I clean the PlaceHolder..

Could you please help to figure this problem out?

Thanks,

0
Eyup
Telerik team
answered on 05 Feb 2018, 07:17 AM
Hello Jerome,

This might be related to some ViewState issue. You can try to create the entire RadTreeList structure during Page_Init as demonstrated in this section:
https://docs.telerik.com/devtools/aspnet-ajax/controls/treelist/defining-structure/programmatic-definition#create-the-radtreelist-entirely-in-code-behind-on-page_init

If the issue remains, I suggest that you open a formal support ticket and send us a sample runnable web site to demonstrate the problematic behavior. This will enable us to replicate the issue locally and provide more accurate and precise suggestions.

Regards,
Eyup
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
TreeList
Asked by
Jerome MAILLEY
Top achievements
Rank 1
Answers by
Eyup
Telerik team
Jerome MAILLEY
Top achievements
Rank 1
Share this question
or