using System; using System.Data; using System.Configuration; using System.Collections; using System.Collections.Generic; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Text; namespace ScrewTurn.Wiki { public partial class ClientTree : System.Web.UI.UserControl { private const string ClientTreeItems = "ClientTreeItems"; private string leafCssClass = ""; private string nodeCssClass = ""; private string containerCssClass = ""; protected void Page_Load(object sender, EventArgs e) { Render(); } /// /// Removes all the items in the tree and re-populates it. /// public void PopulateTree() { // Use ViewState to cache data if(Populate == null) ViewState[ClientTreeItems] = new List(); else ViewState[ClientTreeItems] = Populate(this, new PopulateEventArgs()); Render(); } private void Render() { List items = (List)ViewState[ClientTreeItems]; if(items == null) return; StringBuilder sb = new StringBuilder(); sb.Append(@"
"); int iteration = 0; RenderSubTree(items, sb, ref iteration); sb.Append("
"); lblContent.Text = sb.ToString(); } private void RenderSubTree(List items, StringBuilder sb, ref int iteration) { // This method generates the client markup and JavaScript that contains a tree of items // The sub-trees are rendered as nested elements (DIVs) foreach(TreeElement item in items) { iteration++; // Before invoking RenderSubTree recursively! // Render item if(item.SubItems.Count > 0) { // Expanding link string containerId = BuildSubTreeContainerID(iteration); sb.AppendFormat(@"{3}", nodeCssClass, containerId, item.Name, item.Text); sb.AppendFormat(@"
", containerId, containerCssClass); RenderSubTree(item.SubItems, sb, ref iteration); sb.Append("
"); } else { // Action link sb.AppendFormat(@"{3}", leafCssClass, item.OnClientClick, item.Name, item.Text); } } } private string BuildSubTreeContainerID(int iteration) { return string.Format("sub_{0}_{1}", ID, iteration); } /// /// Gets or sets the CSS Class for leaf items. /// public string LeafCssClass { get { return leafCssClass; } set { leafCssClass = value; } } /// /// Gets or sets the CSS Class for folder items. /// public string NodeCssClass { get { return nodeCssClass; } set { nodeCssClass = value; } } /// /// Gets or sets the CSS Class for containers. /// public string ContainerCssClass { get { return containerCssClass; } set { containerCssClass = value; } } /// /// Delegate used for handling the Populate event. /// /// The object that fired the event. /// The event arguments. /// A list of items contained in the expanded sub-tree. public delegate List PopulateEventHandler(object sender, PopulateEventArgs e); /// /// Occurs when a sub-tree is populated. /// public event PopulateEventHandler Populate; } }