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
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
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 ?
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
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,
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
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,
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
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,
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
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>
<
html
xmlns
=
"http://www.w3.org/1999/xhtml"
>
<
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,
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