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