/// <summary> /// Extracts the value of the hidden field, which is the expansion state of all the nodes written /// as a sequence of characters that are one of the following three: /// 'e' - expanded, 'c' - collapsed, 'l' - leaf /// At this point the controls collection has been rebuilt so we go through the expansion state /// string, one character at a time and assign the container controls IsExpanded property based on /// the character. /// </summary> /// <param name="postDataKey">Unique ID of this tree</param> /// <param name="postCollection">Collection that contains the posted fields, including the hidden field we need.</param> /// <returns></returns> public bool LoadPostData(string postDataKey, NameValueCollection postCollection) { //this is the value of the hidden field that is written by javascript //and returned in the postCollection string postedExpansionState = postCollection[postDataKey + this.IdSeparator + this._hiddenFieldId]; int count = 0; foreach (char c in postedExpansionState) { if (this.Controls[count] is TemplatedTreeViewNodeContainer) { TemplatedTreeViewNodeContainer container = (TemplatedTreeViewNodeContainer)this.Controls[count]; switch (c) { case 'e': { container.IsExpanded = true; break; } case 'c': { container.IsExpanded = false; break; } } } count++; } return(false); }
private void ExpandNodesToParent(TemplatedTreeViewNodeContainer node) { int currentDepth = node.Depth; int indexOfNode = this.Controls.IndexOf(node); if (indexOfNode >= 0) { for (int i = indexOfNode; i >= 0; i--) { if (currentDepth == 0) { break; } TemplatedTreeViewNodeContainer checkNode = (TemplatedTreeViewNodeContainer)this.Controls[i]; if (checkNode.Depth == currentDepth) { if (checkNode.HasChildren) { checkNode.IsExpanded = true; } currentDepth--; } } } }
/// <summary> /// Renders the tree view control, the hidden field to store the expansion state, /// and the associated javascript /// </summary> /// <param name="writer"></param> protected override void RenderContents(HtmlTextWriter writer) { int pos = 0; int endingDepth = 1; writer.AddAttribute(HtmlTextWriterAttribute.Class, "rootlist"); writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + this.ClientIDSeparator + "rootlist"); writer.RenderBeginTag(HtmlTextWriterTag.Ul); while (pos < this.Controls.Count) { TemplatedTreeViewNodeContainer ctrl = (TemplatedTreeViewNodeContainer)this.Controls[pos]; //If the current depth is less than the previous depth then close all of the //ul li elements until we are at the correct depth. if (pos != 0) { int prevDepth = ((TemplatedTreeViewNodeContainer)this.Controls[pos - 1]).Depth; if (ctrl.Depth < prevDepth) { ChangeDepth(writer, prevDepth, ctrl.Depth); } } //Draw the opening li writer.Indent++; writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + this.ClientIDSeparator + "ttvnode" + this.ClientIDSeparator + pos.ToString()); writer.AddAttribute(HtmlTextWriterAttribute.Class, GetClassesForNode(ctrl)); writer.RenderBeginTag(HtmlTextWriterTag.Li); //Render the actual contents of the Node ctrl.RenderControl(writer); if (!ctrl.HasChildren) { //Close out the li of this node since there are no children. writer.RenderEndTag(); writer.Indent--; writer.WriteLine(); } else { //This has children so we need to draw an opening ul writer.Indent++; writer.RenderBeginTag(HtmlTextWriterTag.Ul); } endingDepth = ctrl.Depth; pos++; } if (endingDepth != 1) { ChangeDepth(writer, endingDepth, 1); } writer.RenderEndTag(); }
/// <summary> /// If this is not a postback, then the control properties have been loaded from viewstate /// and the CreateChildControls uses this method to create each child control of /// type TemplatedTreeViewNodeContainer. There is no node here to copy the properties from, but at this /// point, the properties are repopulated from the viewstate of each control. The template is /// recreated here for each control and instantiated in the container control. /// The TemplateType list has been restored from the ViewState of the tree view and we can access /// the template types by index (passed in controlNumber). We have to also save off this list so it /// can later be stored in ViewState again. /// </summary> /// <param name="controlNumber"></param> private void CreateControl(int controlNumber) { TemplatedTreeViewNodeContainer container = new TemplatedTreeViewNodeContainer(TemplateTypes[controlNumber]); this.Controls.Add(container); ITemplate nodeTemplate = Templates[TemplateTypes[controlNumber]]; nodeTemplate.InstantiateIn(container); }
private string GetClassesForNode(TemplatedTreeViewNodeContainer ctrl) { string classes = "ttvnode"; if (!string.IsNullOrEmpty(ctrl.TemplateType)) { classes += " " + ctrl.TemplateType; } if (!ctrl.HasChildren) { classes += " ttvleaf"; } if (ctrl.IsSelected) { classes += " selected"; } return(classes); }
/// <summary> /// Called from CreateChildControls if this is not a postback. Creates an instance of /// TemplatedTreeViewNodeContainer and sets some of its properties based on the node passed in. /// This is where the template is created and instantiated in the container control. /// When we post back, we will need to recreate these controls, but will not have the nodes /// available and therefore, will not have the NodeType (or TemplateType) available either. /// So for each of these controls, we store the string of the NodeType into a list /// (_templateTypeList) that will be restored when the ViewState of the tree view gets restored. /// </summary> /// <param name="node"></param> private void CreateControlFromNode(ITemplatedTreeNode node) { TemplatedTreeViewNodeContainer container = new TemplatedTreeViewNodeContainer(node.ItemType, node.Data); this.Controls.Add(container); container.TreeNodeId = node.TemplatedTreeNodeID; container.Path = node.Path; container.IsExpanded = node.IsExpanded; container.IsSelected = node.IsSelected; container.HasChildren = node.HasChildren; ITemplate nodeTemplate = Templates[node.ItemType]; if (nodeTemplate != null) { nodeTemplate.InstantiateIn(container); container.DataBind(); } }