I've been fiddling a bit with the new TreeList control, and manage to add some template columns dynamically.
It seems it's ok to remove a few and add more, but when I remove a lot and add less, I get an exception saying
Invalid column type: "TreeListTemplateColumn".
[Exception: Invalid column type: "TreeListTemplateColumn".]
Telerik.Web.UI.RadTreeList.CreateColumnByType(String columnType) +184
Telerik.Web.UI.TreeListColumnsCollection.System.Web.UI.IStateManager.LoadViewState(Object state) +350
Telerik.Web.UI.RadTreeList.LoadViewState(Object savedState) +97
System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +183
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) +134
System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +221
System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) +134
System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +221
System.Web.UI.Page.LoadAllState() +312
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1661
This also happens when "a lot" of columns has been added and I try to collapse a section.
I guess it's pretty easy to reproduce if you just fiddle a bit with the following page / code.
Try for instance to expand "A", then click "Month", and try to collapse "A".
Or just click "Month" then "Quarter".
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TreeViewTimeline.aspx.cs"
Inherits="Web20.TreeViewTimelineTelerik.TreeViewTimeline" EnableEventValidation="false" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<
html
xmlns
=
"http://www.w3.org/1999/xhtml"
>
<
head
runat
=
"server"
>
<
title
></
title
>
</
head
>
<
body
>
<
form
id
=
"form1"
runat
=
"server"
>
<
asp:ScriptManager
ID
=
"ScriptManager1"
runat
=
"server"
>
</
asp:ScriptManager
>
<
div
>
<
asp:LinkButton
ID
=
"QtrButton"
runat
=
"server"
Text
=
"Quarter"
OnClick
=
"QtrButtonClicked"
/>
<
asp:LinkButton
ID
=
"MonthButton"
runat
=
"server"
Text
=
"Month"
OnClick
=
"MonthButtonClicked"
/>
<
div
id
=
"tbl-container"
>
<
telerik:RadTreeList
runat
=
"server"
ID
=
"treeList"
Skin
=
"Vista"
AutoGenerateColumns
=
"False"
OnInit
=
"treeListInit"
DataKeyNames
=
"ID"
ParentDataKeyNames
=
"Parent"
OnItemCommand
=
"treeListItemCommand"
>
<
Columns
>
<
telerik:TreeListTemplateColumn
UniqueName
=
"Name"
HeaderText
=
"Navn"
>
<
HeaderStyle
/>
<
ItemStyle
/>
<
ItemTemplate
>
<
asp:TextBox
runat
=
"server"
ID
=
"NameTextBox"
Text='<%# Eval("Name") %>' />
</
ItemTemplate
>
</
telerik:TreeListTemplateColumn
>
</
Columns
>
</
telerik:RadTreeList
>
</
div
>
</
div
>
</
form
>
</
body
>
</
html
>
using
System;
using
System.Collections.Generic;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
Telerik.Web.UI;
namespace
Web20.TreeViewTimelineTelerik
{
public
partial
class
TreeViewTimeline : System.Web.UI.Page
{
public
string
Mode
{
get
{
return
ViewState[
"mode"
]
as
string
??
"Quarter"
; }
set
{ ViewState[
"mode"
] = value; }
}
protected
void
Page_Load(
object
sender, EventArgs e)
{
if
(!IsPostBack)
{
BindList();
}
}
private
void
BindList()
{
var list =
new
[]
{
new
Item {ID =
"A"
, Name =
"A"
, Parent =
""
, Periods =
new
Dictionary<
string
, Period>
{{
"Q1"
,
new
Period {Name =
"Q1"
}}, {
"Feb"
,
new
Period {Name=
"1/10"
}}}}
,
new
Item {ID =
"B"
, Name =
"B"
, Parent =
""
}
,
new
Item {ID =
"A.A"
, Name =
"A.A"
, Parent =
"A"
, Periods =
new
Dictionary<
string
, Period>
{{
"Q2"
,
new
Period { Name =
"Qtr 2"
}}, {
"Q3"
,
new
Period {Name=
"Qty 3"
}}, {
"Mar"
,
new
Period{Name=
"2/10"
}} }}
};
treeList.DataSource = list;
treeList.DataBind();
}
protected
void
treeListItemCommand(
object
sender, TreeListCommandEventArgs e)
{
if
(e.CommandName == RadTreeList.ExpandCollapseCommandName)
{
ResetColumns();
}
}
protected
void
treeListInit(
object
sender, EventArgs e)
{
InitColumns();
}
private
void
InitColumns()
{
switch
(Mode)
{
case
"Quarter"
:
string
[] quarters =
new
[] {
"Q1"
,
"Q2"
,
"Q3"
,
"Q4"
};
foreach
(
string
quarter
in
quarters)
treeList.Columns.Add(
new
TreeListTemplateColumn{UniqueName = quarter, HeaderText = quarter, ItemTemplate =
new
PeriodTemplate(quarter)});
break
;
case
"Month"
:
string
[] months =
new
[] {
"Jan"
,
"Feb"
,
"Mar"
,
"Apr"
,
"Mai"
,
"Jun"
,
"Jul"
,
"Aug"
,
"Sep"
,
"Okt"
,
"Nov"
,
"Des"
};
foreach
(
string
month
in
months)
treeList.Columns.Add(
new
TreeListTemplateColumn { UniqueName = month, HeaderText = month, ItemTemplate =
new
PeriodTemplate(month) });
break
;
}
}
private
void
ResetColumns() {
RemoveDynamicColumns();
InitColumns();
BindList();
}
private
void
RemoveDynamicColumns()
{
for
(
int
i = treeList.Columns.Count - 1; i>=1; i--)
treeList.Columns.RemoveAt(i);
}
protected
void
QtrButtonClicked(
object
sender, EventArgs e)
{
Mode =
"Quarter"
;
ResetColumns();
}
protected
void
MonthButtonClicked(
object
sender, EventArgs e)
{
Mode =
"Month"
;
ResetColumns();
}
}
public
class
PeriodTemplate : ITemplate
{
private
readonly
string
quarter;
public
PeriodTemplate(
string
quarter)
{
this
.quarter = quarter;
}
public
void
InstantiateIn(Control container)
{
Label label =
new
Label();
label.EnableViewState =
false
;
label.ID = quarter +
"Label"
;
Item dataItem = (Item)DataBinder.GetDataItem(container.BindingContainer);
if
(dataItem !=
null
&& dataItem.Periods !=
null
)
{
if
(dataItem.Periods.ContainsKey(quarter))
label.Text = dataItem.Periods[quarter].Name;
}
container.Controls.Add(label);
}
}
public
class
Item
{
public
string
ID {
get
;
set
; }
public
string
Parent {
get
;
set
; }
public
string
Name {
get
;
set
; }
public
Dictionary<
string
, Period> Periods {
get
;
set
; }
}
public
class
Period
{
public
string
Name {
get
;
set
; }
}
}
Hope you guys can help. :)
Lars-Erik