2 // System.Web.UI.WebControls.TreeView.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // (C) 2004 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
33 using System.Collections;
35 using System.ComponentModel;
36 using System.Web.Handlers;
37 using System.Collections.Specialized;
39 using System.Security.Permissions;
40 using System.Collections.Generic;
42 namespace System.Web.UI.WebControls
45 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
48 [SupportsEventValidation]
49 [ControlValueProperty ("SelectedValue")]
50 [DefaultEvent ("SelectedNodeChanged")]
51 [Designer ("System.Web.UI.Design.WebControls.TreeViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
52 public class TreeView: HierarchicalDataBoundControl, IPostBackEventHandler, IPostBackDataHandler, ICallbackEventHandler
54 string activeSiteMapPath;
57 TreeNodeStyle leafNodeStyle;
58 TreeNodeStyle nodeStyle;
59 TreeNodeStyle parentNodeStyle;
60 TreeNodeStyle rootNodeStyle;
61 TreeNodeStyle selectedNodeStyle;
63 TreeNodeStyleCollection levelStyles;
64 TreeNodeCollection nodes;
65 TreeNodeBindingCollection dataBindings;
67 TreeNode selectedNode;
70 int registeredStylesCounter = -1;
71 List<Style> levelLinkStyles;
72 Style controlLinkStyle;
74 Style rootNodeLinkStyle;
75 Style parentNodeLinkStyle;
76 Style leafNodeLinkStyle;
77 Style selectedNodeLinkStyle;
78 Style hoverNodeLinkStyle;
80 static readonly object TreeNodeCheckChangedEvent = new object();
81 static readonly object SelectedNodeChangedEvent = new object();
82 static readonly object TreeNodeCollapsedEvent = new object();
83 static readonly object TreeNodeDataBoundEvent = new object();
84 static readonly object TreeNodeExpandedEvent = new object();
85 static readonly object TreeNodePopulateEvent = new object();
87 static Hashtable imageStyles = new Hashtable ();
91 public ImageStyle (string expand, string collapse, string noExpand, string icon, string iconLeaf, string iconRoot) {
100 public string Expand;
101 public string Collapse;
102 public string NoExpand;
103 public string RootIcon;
104 public string ParentIcon;
105 public string LeafIcon;
110 imageStyles [TreeViewImageSet.Arrows] = new ImageStyle ("arrow_plus", "arrow_minus", "arrow_noexpand", null, null, null);
111 imageStyles [TreeViewImageSet.BulletedList] = new ImageStyle (null, null, null, "dot_full", "dot_empty", "dot_full");
112 imageStyles [TreeViewImageSet.BulletedList2] = new ImageStyle (null, null, null, "box_full", "box_empty", "box_full");
113 imageStyles [TreeViewImageSet.BulletedList3] = new ImageStyle (null, null, null, "star_full", "star_empty", "star_full");
114 imageStyles [TreeViewImageSet.BulletedList4] = new ImageStyle (null, null, null, "star_full", "star_empty", "dots");
115 imageStyles [TreeViewImageSet.Contacts] = new ImageStyle ("TreeView_plus", "TreeView_minus", "contact", null, null, null);
116 imageStyles [TreeViewImageSet.Events] = new ImageStyle (null, null, null, "warning", "warning", "warning");
117 imageStyles [TreeViewImageSet.Inbox] = new ImageStyle (null, null, null, "inbox", "inbox", "inbox");
118 imageStyles [TreeViewImageSet.Msdn] = new ImageStyle ("box_plus", "box_minus", "box_noexpand", null, null, null);
119 imageStyles [TreeViewImageSet.Simple] = new ImageStyle (null, null, "box_full", null, null, null);
120 imageStyles [TreeViewImageSet.Simple2] = new ImageStyle (null, null, "box_empty", null, null, null);
123 imageStyles [TreeViewImageSet.News] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null);
124 imageStyles [TreeViewImageSet.Faq] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null);
125 imageStyles [TreeViewImageSet.WindowsHelp] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null);
126 imageStyles [TreeViewImageSet.XPFileExplorer] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", "folder", "file", "computer");
129 public event TreeNodeEventHandler TreeNodeCheckChanged {
130 add { Events.AddHandler (TreeNodeCheckChangedEvent, value); }
131 remove { Events.RemoveHandler (TreeNodeCheckChangedEvent, value); }
134 public event EventHandler SelectedNodeChanged {
135 add { Events.AddHandler (SelectedNodeChangedEvent, value); }
136 remove { Events.RemoveHandler (SelectedNodeChangedEvent, value); }
139 public event TreeNodeEventHandler TreeNodeCollapsed {
140 add { Events.AddHandler (TreeNodeCollapsedEvent, value); }
141 remove { Events.RemoveHandler (TreeNodeCollapsedEvent, value); }
144 public event TreeNodeEventHandler TreeNodeDataBound {
145 add { Events.AddHandler (TreeNodeDataBoundEvent, value); }
146 remove { Events.RemoveHandler (TreeNodeDataBoundEvent, value); }
149 public event TreeNodeEventHandler TreeNodeExpanded {
150 add { Events.AddHandler (TreeNodeExpandedEvent, value); }
151 remove { Events.RemoveHandler (TreeNodeExpandedEvent, value); }
154 public event TreeNodeEventHandler TreeNodePopulate {
155 add { Events.AddHandler (TreeNodePopulateEvent, value); }
156 remove { Events.RemoveHandler (TreeNodePopulateEvent, value); }
159 protected virtual void OnTreeNodeCheckChanged (TreeNodeEventArgs e)
161 if (Events != null) {
162 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeCheckChangedEvent];
163 if (eh != null) eh (this, e);
167 protected virtual void OnSelectedNodeChanged (EventArgs e)
169 if (Events != null) {
170 EventHandler eh = (EventHandler) Events [SelectedNodeChangedEvent];
171 if (eh != null) eh (this, e);
175 protected virtual void OnTreeNodeCollapsed (TreeNodeEventArgs e)
177 if (Events != null) {
178 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeCollapsedEvent];
179 if (eh != null) eh (this, e);
183 protected virtual void OnTreeNodeDataBound (TreeNodeEventArgs e)
185 if (Events != null) {
186 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeDataBoundEvent];
187 if (eh != null) eh (this, e);
191 protected virtual void OnTreeNodeExpanded (TreeNodeEventArgs e)
193 if (Events != null) {
194 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeExpandedEvent];
195 if (eh != null) eh (this, e);
199 protected virtual void OnTreeNodePopulate (TreeNodeEventArgs e)
201 if (Events != null) {
202 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodePopulateEvent];
203 if (eh != null) eh (this, e);
209 public string CollapseImageToolTip {
211 return ViewState.GetString ("CollapseImageToolTip", "Collapse {0}");
214 ViewState["CollapseImageToolTip"] = value;
218 [MonoTODO ("Implement support for this")]
219 [WebCategory ("Behavior")]
220 [WebSysDescription ("Whether the tree will automatically generate bindings.")]
221 [DefaultValue (true)]
222 public bool AutoGenerateDataBindings {
224 return ViewState.GetBool ("AutoGenerateDataBindings", true);
227 ViewState["AutoGenerateDataBindings"] = value;
232 [WebSysDescription ("The url of the image to show when a node can be collapsed.")]
234 [WebCategory ("Appearance")]
235 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
236 public string CollapseImageUrl {
238 return ViewState.GetString ("CollapseImageUrl", "");
241 ViewState["CollapseImageUrl"] = value;
245 [WebCategory ("Data")]
246 [PersistenceMode (PersistenceMode.InnerProperty)]
247 [WebSysDescription ("Bindings for tree nodes.")]
248 [Editor ("System.Web.UI.Design.WebControls.TreeViewBindingsEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
249 [DefaultValue (null)]
250 [MergablePropertyAttribute (false)]
251 public TreeNodeBindingCollection DataBindings {
253 if (dataBindings == null) {
254 dataBindings = new TreeNodeBindingCollection ();
255 if (IsTrackingViewState)
256 ((IStateManager)dataBindings).TrackViewState();
262 [WebCategory ("Behavior")]
263 [WebSysDescription ("Whether the tree view can use client-side script to expand and collapse nodes.")]
265 [DefaultValue (true)]
266 public bool EnableClientScript {
268 return ViewState.GetBool ("EnableClientScript", true);
271 ViewState["EnableClientScript"] = value;
276 [WebCategory ("Behavior")]
277 [WebSysDescription ("The initial expand depth.")]
278 [TypeConverter ("System.Web.UI.WebControls.TreeView+TreeViewExpandDepthConverter, " + Consts.AssemblySystem_Web)]
279 public int ExpandDepth {
281 return ViewState.GetInt ("ExpandDepth", -1);
284 ViewState["ExpandDepth"] = value;
289 public string ExpandImageToolTip {
291 return ViewState.GetString ("ExpandImageToolTip", "Expand {0}");
294 ViewState["ExpandImageToolTip"] = value;
300 [WebSysDescription ("The url of the image to show when a node can be expanded.")]
301 [WebCategory ("Appearance")]
302 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
303 public string ExpandImageUrl {
305 return ViewState.GetString ("ExpandImageUrl", "");
308 ViewState["ExpandImageUrl"] = value;
312 [PersistenceMode (PersistenceMode.InnerProperty)]
313 [NotifyParentProperty (true)]
314 [DefaultValue (null)]
315 [WebCategory ("Styles")]
316 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
317 public Style HoverNodeStyle {
319 if (hoverNodeStyle == null) {
320 hoverNodeStyle = new Style();
321 if (IsTrackingViewState)
322 hoverNodeStyle.TrackViewState();
324 return hoverNodeStyle;
328 [DefaultValue (TreeViewImageSet.Custom)]
329 public TreeViewImageSet ImageSet {
331 return (TreeViewImageSet)ViewState.GetInt ("ImageSet", (int)TreeViewImageSet.Custom);
334 if (!Enum.IsDefined (typeof (TreeViewImageSet), value))
335 throw new ArgumentOutOfRangeException ();
336 ViewState["ImageSet"] = value;
340 [PersistenceMode (PersistenceMode.InnerProperty)]
341 [NotifyParentProperty (true)]
342 [DefaultValue (null)]
343 [WebCategory ("Styles")]
344 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
345 public TreeNodeStyle LeafNodeStyle {
347 if (leafNodeStyle == null) {
348 leafNodeStyle = new TreeNodeStyle ();
349 if (IsTrackingViewState)
350 leafNodeStyle.TrackViewState();
352 return leafNodeStyle;
356 [DefaultValue (null)]
357 [WebCategory ("Styles")]
358 [PersistenceMode (PersistenceMode.InnerProperty)]
359 [Editor ("System.Web.UI.Design.WebControls.TreeNodeStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
360 public TreeNodeStyleCollection LevelStyles {
362 if (levelStyles == null) {
363 levelStyles = new TreeNodeStyleCollection ();
364 if (IsTrackingViewState)
365 ((IStateManager)levelStyles).TrackViewState();
372 public string LineImagesFolder {
374 return ViewState.GetString ("LineImagesFolder", "");
377 ViewState["LineImagesFolder"] = value;
382 public int MaxDataBindDepth {
384 return ViewState.GetInt ("MaxDataBindDepth", -1);
387 ViewState["MaxDataBindDepth"] = value;
392 public int NodeIndent {
394 return ViewState.GetInt ("NodeIndent", 20);
397 ViewState["NodeIndent"] = value;
401 [PersistenceMode (PersistenceMode.InnerProperty)]
402 [Editor ("System.Web.UI.Design.WebControls.TreeNodeCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
403 [DefaultValueAttribute (null)]
404 [MergablePropertyAttribute (false)]
405 public TreeNodeCollection Nodes {
408 nodes = new TreeNodeCollection (this);
409 if (IsTrackingViewState)
410 ((IStateManager)nodes).TrackViewState();
416 [PersistenceMode (PersistenceMode.InnerProperty)]
417 [NotifyParentProperty (true)]
418 [DefaultValue (null)]
419 [WebCategory ("Styles")]
420 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
421 public TreeNodeStyle NodeStyle {
423 if (nodeStyle == null) {
424 nodeStyle = new TreeNodeStyle ();
425 if (IsTrackingViewState)
426 nodeStyle.TrackViewState();
432 [DefaultValue (false)]
433 public bool NodeWrap {
435 return ViewState.GetBool ("NodeWrap", false);
438 ViewState ["NodeWrap"] = value;
444 [WebSysDescription ("The url of the image to show for leaf nodes.")]
445 [WebCategory ("Appearance")]
446 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
447 public string NoExpandImageUrl {
449 return ViewState.GetString ("NoExpandImageUrl", "");
452 ViewState ["NoExpandImageUrl"] = value;
456 [PersistenceMode (PersistenceMode.InnerProperty)]
457 [NotifyParentProperty (true)]
458 [DefaultValue (null)]
459 [WebCategory ("Styles")]
460 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
461 public TreeNodeStyle ParentNodeStyle {
463 if (parentNodeStyle == null) {
464 parentNodeStyle = new TreeNodeStyle ();
465 if (IsTrackingViewState)
466 parentNodeStyle.TrackViewState();
468 return parentNodeStyle;
473 public char PathSeparator {
475 return ViewState.GetChar ("PathSeparator", '/');
478 ViewState ["PathSeparator"] = value;
482 [DefaultValue (true)]
483 public bool PopulateNodesFromClient {
485 return ViewState.GetBool ("PopulateNodesFromClient", true);
488 ViewState ["PopulateNodesFromClient"] = value;
492 [PersistenceMode (PersistenceMode.InnerProperty)]
493 [NotifyParentProperty (true)]
494 [DefaultValue (null)]
495 [WebCategory ("Styles")]
496 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
497 public TreeNodeStyle RootNodeStyle {
499 if (rootNodeStyle == null) {
500 rootNodeStyle = new TreeNodeStyle ();
501 if (IsTrackingViewState)
502 rootNodeStyle.TrackViewState();
504 return rootNodeStyle;
508 [PersistenceMode (PersistenceMode.InnerProperty)]
509 [NotifyParentProperty (true)]
510 [DefaultValue (null)]
511 [WebCategory ("Styles")]
512 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
513 public TreeNodeStyle SelectedNodeStyle {
515 if (selectedNodeStyle == null) {
516 selectedNodeStyle = new TreeNodeStyle ();
517 if (IsTrackingViewState)
518 selectedNodeStyle.TrackViewState();
520 return selectedNodeStyle;
524 Style ControlLinkStyle {
526 if (controlLinkStyle == null) {
527 controlLinkStyle = new Style ();
528 controlLinkStyle.AlwaysRenderTextDecoration = true;
530 return controlLinkStyle;
534 Style NodeLinkStyle {
536 if (nodeLinkStyle == null) {
537 nodeLinkStyle = new Style ();
539 return nodeLinkStyle;
543 Style RootNodeLinkStyle {
545 if (rootNodeLinkStyle == null) {
546 rootNodeLinkStyle = new Style ();
548 return rootNodeLinkStyle;
552 Style ParentNodeLinkStyle {
554 if (parentNodeLinkStyle == null) {
555 parentNodeLinkStyle = new Style ();
557 return parentNodeLinkStyle;
561 Style SelectedNodeLinkStyle {
563 if (selectedNodeLinkStyle == null) {
564 selectedNodeLinkStyle = new Style ();
566 return selectedNodeLinkStyle;
570 Style LeafNodeLinkStyle {
572 if (leafNodeLinkStyle == null) {
573 leafNodeLinkStyle = new Style ();
575 return leafNodeLinkStyle;
579 Style HoverNodeLinkStyle {
581 if (hoverNodeLinkStyle == null) {
582 hoverNodeLinkStyle = new Style ();
584 return hoverNodeLinkStyle;
588 [DefaultValue (TreeNodeTypes.None)]
589 public TreeNodeTypes ShowCheckBoxes {
591 return (TreeNodeTypes)ViewState.GetInt ("ShowCheckBoxes", (int)TreeNodeTypes.None);
595 throw new ArgumentOutOfRangeException ();
596 ViewState ["ShowCheckBoxes"] = value;
600 [DefaultValue (true)]
601 public bool ShowExpandCollapse {
603 return ViewState.GetBool ("ShowExpandCollapse", true);
606 ViewState ["ShowExpandCollapse"] = value;
610 [DefaultValue (false)]
611 public bool ShowLines {
613 return ViewState.GetBool ("ShowLines", false);
616 ViewState ["ShowLines"] = value;
621 public string SkipLinkText
624 return ViewState.GetString ("SkipLinkText", "Skip Navigation Links.");
627 ViewState ["SkipLinkText"] = value;
633 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
634 public TreeNode SelectedNode {
635 get { return selectedNode; }
640 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
641 public string SelectedValue {
642 get { return selectedNode != null ? selectedNode.Value : ""; }
646 public string Target {
648 return ViewState.GetString ("Target", "");
651 ViewState ["Target"] = value;
655 [MonoTODO ("why override?")]
656 public override bool Visible
662 base.Visible = value;
667 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
668 public TreeNodeCollection CheckedNodes {
670 TreeNodeCollection col = new TreeNodeCollection ();
671 FindCheckedNodes (Nodes, col);
676 void FindCheckedNodes (TreeNodeCollection nodeList, TreeNodeCollection result)
678 foreach (TreeNode node in nodeList) {
679 if (node.Checked) result.Add (node, false);
680 FindCheckedNodes (node.ChildNodes, result);
684 public void ExpandAll ()
686 foreach (TreeNode node in Nodes)
690 public void CollapseAll ()
692 foreach (TreeNode node in Nodes)
696 public TreeNode FindNode (string valuePath)
698 if (valuePath == null) throw new ArgumentNullException ("valuePath");
699 string[] path = valuePath.Split (PathSeparator);
701 TreeNodeCollection col = Nodes;
702 bool foundBranch = true;
703 while (col.Count > 0 && foundBranch) {
705 foreach (TreeNode node in col) {
706 if (node.Value == path [n]) {
707 if (++n == path.Length) return node;
708 col = node.ChildNodes;
717 ImageStyle GetImageStyle ()
719 if (ImageSet != TreeViewImageSet.Custom)
720 return (ImageStyle) imageStyles [ImageSet];
725 protected override HtmlTextWriterTag TagKey {
726 get { return HtmlTextWriterTag.Div; }
729 protected internal virtual TreeNode CreateNode ()
731 return new TreeNode (this);
734 public sealed override void DataBind ()
739 protected void SetNodeDataBound (TreeNode node, bool dataBound)
741 node.SetDataBound (dataBound);
744 protected void SetNodeDataPath (TreeNode node, string dataPath)
746 node.SetDataPath (dataPath);
749 protected void SetNodeDataItem (TreeNode node, object dataItem)
751 node.SetDataItem (dataItem);
754 protected internal override void OnInit (EventArgs e)
759 internal void SetSelectedNode (TreeNode node, bool loading)
761 if (selectedNode == node) return;
762 if (selectedNode != null)
763 selectedNode.SelectedFlag = false;
766 OnSelectedNodeChanged (new TreeNodeEventArgs (selectedNode));
769 internal void NotifyCheckChanged (TreeNode node)
771 OnTreeNodeCheckChanged (new TreeNodeEventArgs (node));
774 internal void NotifyExpandedChanged (TreeNode node)
776 if (node.Expanded.HasValue && node.Expanded.Value)
777 OnTreeNodeExpanded (new TreeNodeEventArgs (node));
778 else if (node.Expanded.HasValue && node.IsParentNode)
779 OnTreeNodeCollapsed (new TreeNodeEventArgs (node));
782 internal void NotifyPopulateRequired (TreeNode node)
784 OnTreeNodePopulate (new TreeNodeEventArgs (node));
787 protected override void TrackViewState()
791 base.TrackViewState();
792 if (hoverNodeStyle != null) {
793 hoverNodeStyle.TrackViewState();
795 if (leafNodeStyle != null) {
796 leafNodeStyle.TrackViewState();
798 if (levelStyles != null && levelStyles.Count > 0) {
799 ((IStateManager)levelStyles).TrackViewState();
801 if (nodeStyle != null) {
802 nodeStyle.TrackViewState();
804 if (parentNodeStyle != null) {
805 parentNodeStyle.TrackViewState();
807 if (rootNodeStyle != null) {
808 rootNodeStyle.TrackViewState();
810 if (selectedNodeStyle != null) {
811 selectedNodeStyle.TrackViewState();
813 if (dataBindings != null) {
814 ((IStateManager)dataBindings).TrackViewState ();
817 ((IStateManager)nodes).TrackViewState();;
821 protected override object SaveViewState()
823 object[] states = new object [10];
824 states[0] = base.SaveViewState();
825 states[1] = (hoverNodeStyle == null ? null : hoverNodeStyle.SaveViewState());
826 states[2] = (leafNodeStyle == null ? null : leafNodeStyle.SaveViewState());
827 states[3] = (levelStyles == null ? null : ((IStateManager)levelStyles).SaveViewState());
828 states[4] = (nodeStyle == null ? null : nodeStyle.SaveViewState());
829 states[5] = (parentNodeStyle == null ? null : parentNodeStyle.SaveViewState());
830 states[6] = (rootNodeStyle == null ? null : rootNodeStyle.SaveViewState());
831 states[7] = (selectedNodeStyle == null ? null : selectedNodeStyle.SaveViewState());
832 states[8] = (dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState());
833 states[9] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
835 for (int i = states.Length - 1; i >= 0; i--) {
836 if (states [i] != null)
843 protected override void LoadViewState (object savedState)
845 if (savedState == null)
848 object [] states = (object []) savedState;
849 base.LoadViewState (states[0]);
851 if (states[1] != null)
852 HoverNodeStyle.LoadViewState (states[1]);
853 if (states[2] != null)
854 LeafNodeStyle.LoadViewState(states[2]);
855 if (states[3] != null)
856 ((IStateManager)LevelStyles).LoadViewState(states[3]);
857 if (states[4] != null)
858 NodeStyle.LoadViewState(states[4]);
859 if (states[5] != null)
860 ParentNodeStyle.LoadViewState(states[5]);
861 if (states[6] != null)
862 RootNodeStyle.LoadViewState(states[6]);
863 if (states[7] != null)
864 SelectedNodeStyle.LoadViewState(states[7]);
865 if (states[8] != null)
866 ((IStateManager)DataBindings).LoadViewState(states[8]);
867 if (states[9] != null)
868 ((IStateManager)Nodes).LoadViewState(states[9]);
871 protected virtual void RaisePostBackEvent (string eventArgument)
873 ValidateEvent (UniqueID, eventArgument);
874 string[] args = eventArgument.Split ('|');
875 TreeNode node = FindNodeByPos (args[1]);
876 if (node == null) return;
878 if (args [0] == "sel")
879 HandleSelectEvent (node);
880 else if (args [0] == "ec")
881 HandleExpandCollapseEvent (node);
884 void HandleSelectEvent (TreeNode node)
886 switch (node.SelectAction) {
887 case TreeNodeSelectAction.Select:
890 case TreeNodeSelectAction.Expand:
893 case TreeNodeSelectAction.SelectExpand:
900 void HandleExpandCollapseEvent (TreeNode node)
902 node.ToggleExpandState ();
905 protected virtual void RaisePostDataChangedEvent ()
909 string callbackResult;
910 protected virtual void RaiseCallbackEvent (string eventArgs)
912 RequiresDataBinding = true;
915 TreeNode node = FindNodeByPos (eventArgs);
916 ArrayList levelLines = new ArrayList ();
919 int childCount = nd.Parent != null ? nd.Parent.ChildNodes.Count : Nodes.Count;
920 levelLines.Insert (0, (nd.Index < childCount - 1) ? this : null);
924 StringWriter sw = new StringWriter ();
925 HtmlTextWriter writer = new HtmlTextWriter (sw);
926 EnsureStylesPrepared ();
928 node.Expanded = true;
929 int num = node.ChildNodes.Count;
930 for (int n=0; n<num; n++)
931 RenderNode (writer, node.ChildNodes [n], node.Depth + 1, levelLines, true, n<num-1);
933 string res = sw.ToString ();
934 callbackResult = res != "" ? res : "*";
937 protected virtual string GetCallbackResult ()
939 return callbackResult;
942 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
944 RaisePostBackEvent (eventArgument);
947 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
949 return LoadPostData (postDataKey, postCollection);
952 void IPostBackDataHandler.RaisePostDataChangedEvent ()
954 RaisePostDataChangedEvent ();
957 void ICallbackEventHandler.RaiseCallbackEvent (string eventArgs)
959 RaiseCallbackEvent (eventArgs);
962 string ICallbackEventHandler.GetCallbackResult ()
964 return GetCallbackResult ();
967 protected override ControlCollection CreateControlCollection ()
969 return new EmptyControlCollection (this);
972 protected internal override void PerformDataBinding ()
974 base.PerformDataBinding ();
975 InitializeDataBindings ();
976 HierarchicalDataSourceView data = GetData ("");
980 IHierarchicalEnumerable e = data.Select ();
981 FillBoundChildrenRecursive (e, Nodes);
984 void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, TreeNodeCollection nodeCollection)
986 if (hEnumerable == null)
989 foreach (object obj in hEnumerable) {
990 IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
991 TreeNode child = new TreeNode ();
992 nodeCollection.Add (child);
994 OnTreeNodeDataBound (new TreeNodeEventArgs (child));
996 if (MaxDataBindDepth >= 0 && child.Depth == MaxDataBindDepth)
999 if (hdata == null || !hdata.HasChildren)
1002 IHierarchicalEnumerable e = hdata.GetChildren ();
1003 FillBoundChildrenRecursive (e, child.ChildNodes);
1007 protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection)
1011 if (EnableClientScript && PopulateNodesFromClient) {
1012 string states = postCollection [ClientID + "_PopulatedStates"];
1013 if (states != null) {
1014 foreach (string id in states.Split ('|')) {
1015 if (String.IsNullOrEmpty(id))
1017 TreeNode node = FindNodeByPos (id);
1018 if (node != null && node.PopulateOnDemand && !node.Populated)
1025 UnsetCheckStates (Nodes, postCollection);
1026 SetCheckStates (postCollection);
1028 if (EnableClientScript) {
1029 string states = postCollection [ClientID + "_ExpandStates"];
1030 if (states != null) {
1031 string[] ids = states.Split ('|');
1032 UnsetExpandStates (Nodes, ids);
1033 SetExpandStates (ids);
1036 UnsetExpandStates (Nodes, new string[0]);
1042 protected internal override void OnPreRender (EventArgs e)
1044 base.OnPreRender (e);
1048 Page.RegisterRequiresPostBack (this);
1050 if (EnableClientScript && !Page.ClientScript.IsClientScriptIncludeRegistered (typeof(TreeView), "TreeView.js")) {
1051 string url = Page.ClientScript.GetWebResourceUrl (typeof(TreeView), "TreeView.js");
1052 Page.ClientScript.RegisterClientScriptInclude (typeof(TreeView), "TreeView.js", url);
1056 string ctree = ClientID + "_data";
1057 string script = string.Format ("var {0} = new Object ();\n", ctree);
1058 script += string.Format ("{0}.treeId = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (ClientID));
1059 script += string.Format ("{0}.uid = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (UniqueID));
1060 script += string.Format ("{0}.showImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (ShowExpandCollapse));
1062 if (ShowExpandCollapse) {
1063 ImageStyle imageStyle = GetImageStyle ();
1064 script += string.Format ("{0}.expandImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("plus", imageStyle)));
1065 script += string.Format ("{0}.collapseImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("minus", imageStyle)));
1066 if (PopulateNodesFromClient)
1067 script += string.Format ("{0}.noExpandImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("noexpand", imageStyle)));
1071 script += string.Format ("{0}.form = {1};\n", ctree, Page.theForm);
1072 script += string.Format (
1073 @"{0}.PopulateNode = function(nodeId) {{
1074 " + Page.WebFormScriptReference + @".__theFormPostData = """";
1075 " + Page.WebFormScriptReference + @".__theFormPostCollection = new Array();
1076 " + Page.WebFormScriptReference + @".WebForm_InitCallback();
1079 ", ctree, Page.ClientScript.GetCallbackEventReference ("this.uid", "nodeId", "TreeView_PopulateCallback", "this.treeId + \" \" + nodeId", "TreeView_PopulateCallback", false));
1080 script += string.Format ("{0}.populateFromClient = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (PopulateNodesFromClient));
1081 script += string.Format ("{0}.expandAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (true, null)));
1082 script += string.Format ("{0}.collapseAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (false, null)));
1084 if (!Page.IsPostBack) {
1085 SetNodesExpandedToDepthRecursive (Nodes);
1088 if (EnableClientScript) {
1089 Page.ClientScript.RegisterHiddenField (ClientID + "_ExpandStates", GetExpandStates ());
1091 // Make sure the basic script infrastructure is rendered
1092 Page.ClientScript.RegisterWebFormClientScript ();
1095 if (EnableClientScript && PopulateNodesFromClient) {
1096 Page.ClientScript.RegisterHiddenField (ClientID + "_PopulatedStates", "|");
1099 EnsureStylesPrepared ();
1101 if (hoverNodeStyle != null) {
1102 if (Page.Header == null)
1103 throw new InvalidOperationException ("Using TreeView.HoverNodeStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
1104 RegisterStyle (HoverNodeStyle, HoverNodeLinkStyle);
1105 script += string.Format ("{0}.hoverClass = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (HoverNodeStyle.RegisteredCssClass));
1106 script += string.Format ("{0}.hoverLinkClass = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (HoverNodeLinkStyle.RegisteredCssClass));
1109 Page.ClientScript.RegisterStartupScript (typeof(TreeView), this.UniqueID, script, true);
1113 void EnsureStylesPrepared () {
1116 stylesPrepared = true;
1120 void PrepareStyles () {
1121 // The order in which styles are defined matters when more than one class
1122 // is assigned to an element
1123 ControlLinkStyle.CopyTextStylesFrom (ControlStyle);
1124 RegisterStyle (ControlLinkStyle);
1126 if (nodeStyle != null)
1127 RegisterStyle (NodeStyle, NodeLinkStyle);
1129 if (rootNodeStyle != null)
1130 RegisterStyle (RootNodeStyle, RootNodeLinkStyle);
1132 if (parentNodeStyle != null)
1133 RegisterStyle (ParentNodeStyle, ParentNodeLinkStyle);
1135 if (leafNodeStyle != null)
1136 RegisterStyle (LeafNodeStyle, LeafNodeLinkStyle);
1139 if (levelStyles != null && levelStyles.Count > 0) {
1140 levelLinkStyles = new List<Style> (levelStyles.Count);
1141 foreach (Style style in levelStyles) {
1142 Style linkStyle = new Style ();
1143 levelLinkStyles.Add (linkStyle);
1144 RegisterStyle (style, linkStyle);
1148 if (selectedNodeStyle != null)
1149 RegisterStyle (SelectedNodeStyle, SelectedNodeLinkStyle);
1152 void SetNodesExpandedToDepthRecursive (TreeNodeCollection nodes) {
1153 foreach (TreeNode node in nodes) {
1154 if (!node.Expanded.HasValue) {
1155 if (ExpandDepth < 0 || node.Depth < ExpandDepth)
1156 node.Expanded = true;
1158 SetNodesExpandedToDepthRecursive (node.ChildNodes);
1162 string IncrementStyleClassName () {
1163 registeredStylesCounter++;
1164 return ClientID + "_" + registeredStylesCounter;
1167 void RegisterStyle (Style baseStyle, Style linkStyle) {
1168 linkStyle.CopyTextStylesFrom (baseStyle);
1169 linkStyle.BorderStyle = BorderStyle.None;
1170 baseStyle.Font.Reset ();
1171 RegisterStyle (linkStyle);
1172 RegisterStyle (baseStyle);
1175 void RegisterStyle (Style baseStyle) {
1176 if (Page.Header == null)
1178 string className = IncrementStyleClassName ().Trim ('_');
1179 baseStyle.SetRegisteredCssClass (className);
1180 Page.Header.StyleSheet.CreateStyleRule (baseStyle, this, "." + className);
1183 string GetBindingKey (string dataMember, int depth)
1185 return dataMember + " " + depth;
1188 void InitializeDataBindings () {
1189 if (dataBindings != null && dataBindings.Count > 0) {
1190 bindings = new Hashtable ();
1191 foreach (TreeNodeBinding bin in dataBindings) {
1192 string key = GetBindingKey (bin.DataMember, bin.Depth);
1193 if (!bindings.ContainsKey(key))
1194 bindings [key] = bin;
1201 internal TreeNodeBinding FindBindingForNode (string type, int depth)
1203 if (bindings == null)
1206 TreeNodeBinding bin = (TreeNodeBinding) bindings [GetBindingKey (type, depth)];
1207 if (bin != null) return bin;
1209 bin = (TreeNodeBinding) bindings [GetBindingKey (type, -1)];
1210 if (bin != null) return bin;
1212 bin = (TreeNodeBinding) bindings [GetBindingKey ("", depth)];
1213 if (bin != null) return bin;
1215 return (TreeNodeBinding) bindings [GetBindingKey ("", -1)];
1218 internal void DecorateNode(TreeNode node)
1223 if (node.ImageUrl != null && node.ImageUrl.Length > 0)
1226 if (node.IsRootNode && rootNodeStyle != null) {
1227 node.ImageUrl = rootNodeStyle.ImageUrl;
1230 if (node.IsParentNode && parentNodeStyle != null) {
1231 node.ImageUrl = parentNodeStyle.ImageUrl;
1234 if (node.IsLeafNode && leafNodeStyle != null)
1235 node.ImageUrl = leafNodeStyle.ImageUrl;
1238 protected internal override void RenderContents (HtmlTextWriter writer)
1240 SiteMapDataSource siteMap = GetDataSource () as SiteMapDataSource;
1241 bool checkSitePath = IsBoundUsingDataSourceID && siteMap != null;
1243 if (checkSitePath) {
1244 IHierarchyData data = siteMap.Provider.CurrentNode;
1246 activeSiteMapPath = data.Path;
1249 ArrayList levelLines = new ArrayList ();
1250 int num = Nodes.Count;
1251 for (int n=0; n<num; n++)
1252 RenderNode (writer, Nodes [n], 0, levelLines, n>0, n<num-1);
1255 protected override void AddAttributesToRender(HtmlTextWriter writer)
1257 base.AddAttributesToRender (writer);
1260 public override void RenderBeginTag (HtmlTextWriter writer)
1262 if (SkipLinkText != "") {
1263 writer.AddAttribute (HtmlTextWriterAttribute.Href, "#" + ClientID + "_SkipLink");
1264 writer.RenderBeginTag (HtmlTextWriterTag.A);
1266 Image img = new Image ();
1267 ClientScriptManager csm = new ClientScriptManager (null);
1268 img.ImageUrl = csm.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif");
1269 img.Attributes.Add ("height", "0");
1270 img.Attributes.Add ("width", "0");
1271 img.AlternateText = SkipLinkText;
1272 img.Render (writer);
1274 writer.RenderEndTag ();
1276 base.RenderBeginTag (writer);
1279 public override void RenderEndTag (HtmlTextWriter writer)
1281 base.RenderEndTag (writer);
1283 if (SkipLinkText != "") {
1284 writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID + "_SkipLink");
1285 writer.RenderBeginTag (HtmlTextWriterTag.A);
1286 writer.RenderEndTag ();
1290 void RenderNode (HtmlTextWriter writer, TreeNode node, int level, ArrayList levelLines, bool hasPrevious, bool hasNext)
1295 bool clientExpand = EnableClientScript && Events [TreeNodeCollapsedEvent] == null && Events [TreeNodeExpandedEvent] == null;
1296 ImageStyle imageStyle = GetImageStyle ();
1297 bool renderChildNodes = node.Expanded.HasValue && node.Expanded.Value;
1299 if (clientExpand && !renderChildNodes)
1300 renderChildNodes = (!node.PopulateOnDemand || node.Populated);
1304 if (renderChildNodes)
1305 hasChildNodes = node.ChildNodes.Count > 0;
1307 hasChildNodes = (node.PopulateOnDemand && !node.Populated) || node.ChildNodes.Count > 0;
1309 writer.AddAttribute ("cellpadding", "0", false);
1310 writer.AddAttribute ("cellspacing", "0", false);
1311 writer.AddStyleAttribute ("border-width", "0");
1312 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1314 Unit nodeSpacing = GetNodeSpacing (node);
1316 if (nodeSpacing != Unit.Empty && (node.Depth > 0 || node.Index > 0))
1317 RenderMenuItemSpacing (writer, nodeSpacing);
1319 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1321 // Vertical lines from previous levels
1323 nodeImage = GetNodeImageUrl ("i", imageStyle);
1324 for (int n=0; n<level; n++) {
1325 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1326 writer.AddStyleAttribute ("width", NodeIndent + "px");
1327 writer.AddStyleAttribute ("height", "1px");
1328 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1329 if (ShowLines && levelLines [n] != null) {
1330 writer.AddAttribute ("src", nodeImage);
1331 writer.AddAttribute (HtmlTextWriterAttribute.Alt, "", false);
1332 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1333 writer.RenderEndTag ();
1335 writer.RenderEndTag ();
1336 writer.RenderEndTag (); // TD
1339 // Node image + line
1341 if (ShowExpandCollapse || ShowLines) {
1342 bool buttonImage = false;
1343 string tooltip = "";
1347 if (hasPrevious && hasNext) shape = "t";
1348 else if (hasPrevious && !hasNext) shape = "l";
1349 else if (!hasPrevious && hasNext) shape = "r";
1350 else shape = "dash";
1353 if (ShowExpandCollapse) {
1354 if (hasChildNodes) {
1356 if (node.Expanded.HasValue && node.Expanded.Value) shape += "minus";
1357 else shape += "plus";
1358 tooltip = GetNodeImageToolTip (!(node.Expanded.HasValue && node.Expanded.Value), node.Text);
1359 } else if (!ShowLines)
1364 nodeImage = GetNodeImageUrl (shape, imageStyle);
1365 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1368 if (!clientExpand || (!PopulateNodesFromClient && node.PopulateOnDemand && !node.Populated))
1369 writer.AddAttribute ("href", GetClientEvent (node, "ec"));
1371 writer.AddAttribute ("href", GetClientExpandEvent(node));
1372 writer.RenderBeginTag (HtmlTextWriterTag.A); // Anchor
1375 writer.AddAttribute ("alt", tooltip);
1377 if (buttonImage && clientExpand)
1378 writer.AddAttribute ("id", GetNodeClientId (node, "img"));
1379 writer.AddAttribute ("src", nodeImage);
1381 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
1382 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1383 writer.RenderEndTag ();
1386 writer.RenderEndTag (); // Anchor
1388 writer.RenderEndTag (); // TD
1394 string imageUrl = node.ImageUrl.Length > 0 ? ResolveClientUrl (node.ImageUrl) : null;
1395 if (String.IsNullOrEmpty (imageUrl) && imageStyle != null) {
1396 if (imageStyle.RootIcon != null && node.IsRootNode)
1397 imageUrl = GetNodeIconUrl (imageStyle.RootIcon);
1398 else if (imageStyle.ParentIcon != null && node.IsParentNode)
1399 imageUrl = GetNodeIconUrl (imageStyle.ParentIcon);
1400 else if (imageStyle.LeafIcon != null && node.IsLeafNode)
1401 imageUrl = GetNodeIconUrl (imageStyle.LeafIcon);
1404 if (level < LevelStyles.Count && LevelStyles [level].ImageUrl != null)
1405 imageUrl = ResolveClientUrl (LevelStyles [level].ImageUrl);
1407 if (!String.IsNullOrEmpty (imageUrl)) {
1408 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1409 BeginNodeTag (writer, node, clientExpand);
1410 writer.AddAttribute ("src", imageUrl);
1411 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
1412 writer.AddAttribute ("alt", node.ImageToolTip);
1413 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1414 writer.RenderEndTag (); // IMG
1415 writer.RenderEndTag (); // style tag
1416 writer.RenderEndTag (); // TD
1420 writer.AddStyleAttribute ("white-space", "nowrap");
1422 bool nodeIsSelected = node == SelectedNode && selectedNodeStyle != null;
1423 if (!nodeIsSelected && selectedNodeStyle != null) {
1424 if (!String.IsNullOrEmpty (activeSiteMapPath))
1425 nodeIsSelected = String.Compare (activeSiteMapPath,
1427 HttpRuntime.CaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) == 0;
1430 AddNodeStyle (writer, node, level, nodeIsSelected);
1431 if (EnableClientScript) {
1432 writer.AddAttribute ("onmouseout", "TreeView_UnhoverNode(this)", false);
1433 writer.AddAttribute ("onmouseover", "TreeView_HoverNode('" + ClientID + "', this)");
1435 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1439 if (node.ShowCheckBoxInternal) {
1440 writer.AddAttribute ("name", ClientID + "_cs_" + node.Path);
1441 writer.AddAttribute ("type", "checkbox", false);
1442 writer.AddAttribute ("title", node.Text);
1443 if (node.Checked) writer.AddAttribute ("checked", "checked", false);
1444 writer.RenderBeginTag (HtmlTextWriterTag.Input); // INPUT
1445 writer.RenderEndTag (); // INPUT
1450 node.BeginRenderText (writer);
1453 writer.AddAttribute ("id", GetNodeClientId (node, "txt"));
1454 AddNodeLinkStyle (writer, node, level, nodeIsSelected);
1455 BeginNodeTag (writer, node, clientExpand);
1456 writer.Write (node.Text);
1457 writer.RenderEndTag (); // style tag
1459 node.EndRenderText (writer);
1461 writer.RenderEndTag (); // TD
1463 writer.RenderEndTag (); // TR
1465 if (nodeSpacing != Unit.Empty)
1466 RenderMenuItemSpacing (writer, nodeSpacing);
1468 writer.RenderEndTag (); // TABLE
1472 if (hasChildNodes) {
1473 if (level >= levelLines.Count) {
1475 levelLines.Add (this);
1477 levelLines.Add (null);
1480 levelLines [level] = this;
1482 levelLines [level] = null;
1486 if (!(node.Expanded.HasValue && node.Expanded.Value))
1487 writer.AddStyleAttribute ("display", "none");
1489 writer.AddStyleAttribute ("display", "block");
1490 writer.AddAttribute ("id", GetNodeClientId (node, null));
1491 writer.RenderBeginTag (HtmlTextWriterTag.Span);
1493 if (renderChildNodes) {
1494 AddChildrenPadding (writer, node);
1495 int num = node.ChildNodes.Count;
1496 for (int n=0; n<num; n++)
1497 RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
1499 AddChildrenPadding (writer, node);
1501 writer.RenderEndTag (); // SPAN
1502 } else if (renderChildNodes) {
1503 AddChildrenPadding (writer, node);
1504 int num = node.ChildNodes.Count;
1505 for (int n=0; n<num; n++)
1506 RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
1508 AddChildrenPadding (writer, node);
1513 void AddChildrenPadding (HtmlTextWriter writer, TreeNode node)
1515 int level = node.Depth;
1516 Unit cnp = Unit.Empty;
1518 if (levelStyles != null && level < levelStyles.Count)
1519 cnp = levelStyles [level].ChildNodesPadding;
1520 if (cnp.IsEmpty && nodeStyle != null)
1521 cnp = nodeStyle.ChildNodesPadding;
1524 if (cnp.IsEmpty || (value = cnp.Value) == 0 || cnp.Type != UnitType.Pixel)
1527 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1528 writer.AddAttribute ("height", ((int) value).ToString (), false);
1529 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1530 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1531 writer.RenderEndTag (); // td
1532 writer.RenderEndTag (); // tr
1533 writer.RenderEndTag (); // table
1536 void RenderMenuItemSpacing (HtmlTextWriter writer, Unit itemSpacing) {
1537 writer.AddStyleAttribute ("height", itemSpacing.ToString ());
1538 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1539 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1540 writer.RenderEndTag ();
1541 writer.RenderEndTag ();
1544 Unit GetNodeSpacing (TreeNode node) {
1545 if (node.Selected && selectedNodeStyle != null && selectedNodeStyle.NodeSpacing != Unit.Empty) {
1546 return selectedNodeStyle.NodeSpacing;
1549 if (levelStyles != null && node.Depth < levelStyles.Count && levelStyles [node.Depth].NodeSpacing != Unit.Empty) {
1550 return levelStyles [node.Depth].NodeSpacing;
1553 if (node.IsLeafNode) {
1554 if (leafNodeStyle != null && leafNodeStyle.NodeSpacing != Unit.Empty)
1555 return leafNodeStyle.NodeSpacing;
1557 else if (node.IsRootNode) {
1558 if (rootNodeStyle != null && rootNodeStyle.NodeSpacing != Unit.Empty)
1559 return rootNodeStyle.NodeSpacing;
1561 else if (node.IsParentNode) {
1562 if (parentNodeStyle != null && parentNodeStyle.NodeSpacing != Unit.Empty)
1563 return parentNodeStyle.NodeSpacing;
1566 if (nodeStyle != null)
1567 return nodeStyle.NodeSpacing;
1572 void AddNodeStyle (HtmlTextWriter writer, TreeNode node, int level, bool nodeIsSelected)
1574 TreeNodeStyle style = new TreeNodeStyle ();
1575 if (Page.Header != null) {
1576 // styles are registered
1577 if (nodeStyle != null) {
1578 style.AddCssClass (nodeStyle.CssClass);
1579 style.AddCssClass (nodeStyle.RegisteredCssClass);
1581 if (node.IsLeafNode) {
1582 if (leafNodeStyle != null) {
1583 style.AddCssClass (leafNodeStyle.CssClass);
1584 style.AddCssClass (leafNodeStyle.RegisteredCssClass);
1586 } else if (node.IsRootNode) {
1587 if (rootNodeStyle != null) {
1588 style.AddCssClass (rootNodeStyle.CssClass);
1589 style.AddCssClass (rootNodeStyle.RegisteredCssClass);
1591 } else if (node.IsParentNode) {
1592 if (parentNodeStyle != null) {
1593 style.AddCssClass (parentNodeStyle.CssClass);
1594 style.AddCssClass (parentNodeStyle.RegisteredCssClass);
1597 if (levelStyles != null && levelStyles.Count > level) {
1598 style.AddCssClass (levelStyles [level].CssClass);
1599 style.AddCssClass (levelStyles [level].RegisteredCssClass);
1602 if (nodeIsSelected) {
1603 style.AddCssClass (selectedNodeStyle.CssClass);
1604 style.AddCssClass (selectedNodeStyle.RegisteredCssClass);
1607 // styles are not registered
1608 if (nodeStyle != null) {
1609 style.CopyFrom (nodeStyle);
1611 if (node.IsLeafNode) {
1612 if (leafNodeStyle != null) {
1613 style.CopyFrom (leafNodeStyle);
1616 else if (node.IsRootNode) {
1617 if (rootNodeStyle != null) {
1618 style.CopyFrom (rootNodeStyle);
1621 else if (node.IsParentNode) {
1622 if (parentNodeStyle != null) {
1623 style.CopyFrom (parentNodeStyle);
1626 if (levelStyles != null && levelStyles.Count > level) {
1627 style.CopyFrom (levelStyles [level]);
1630 if (nodeIsSelected) {
1631 style.CopyFrom (selectedNodeStyle);
1634 style.AddAttributesToRender (writer);
1637 void AddNodeLinkStyle (HtmlTextWriter writer, TreeNode node, int level, bool nodeIsSelected)
1639 Style style = new Style ();
1640 if (Page.Header != null) {
1641 // styles are registered
1642 style.AddCssClass (ControlLinkStyle.RegisteredCssClass);
1644 if (nodeStyle != null) {
1645 style.AddCssClass (nodeLinkStyle.CssClass);
1646 style.AddCssClass (nodeLinkStyle.RegisteredCssClass);
1648 if (node.IsLeafNode) {
1649 if (leafNodeStyle != null) {
1650 style.AddCssClass (leafNodeLinkStyle.CssClass);
1651 style.AddCssClass (leafNodeLinkStyle.RegisteredCssClass);
1654 else if (node.IsRootNode) {
1655 if (rootNodeStyle != null) {
1656 style.AddCssClass (rootNodeLinkStyle.CssClass);
1657 style.AddCssClass (rootNodeLinkStyle.RegisteredCssClass);
1660 else if (node.IsParentNode) {
1661 if (parentNodeStyle != null) {
1662 style.AddCssClass (parentNodeLinkStyle.CssClass);
1663 style.AddCssClass (parentNodeLinkStyle.RegisteredCssClass);
1666 if (levelStyles != null && levelStyles.Count > level) {
1667 style.AddCssClass (levelLinkStyles [level].CssClass);
1668 style.AddCssClass (levelLinkStyles [level].RegisteredCssClass);
1670 if (nodeIsSelected) {
1671 style.AddCssClass (selectedNodeLinkStyle.CssClass);
1672 style.AddCssClass (selectedNodeLinkStyle.RegisteredCssClass);
1676 // styles are not registered
1677 style.CopyFrom (ControlLinkStyle);
1678 if (nodeStyle != null) {
1679 style.CopyFrom (nodeLinkStyle);
1681 if (node.IsLeafNode) {
1682 if (node.IsLeafNode && leafNodeStyle != null) {
1683 style.CopyFrom (leafNodeLinkStyle);
1686 else if (node.IsRootNode) {
1687 if (node.IsRootNode && rootNodeStyle != null) {
1688 style.CopyFrom (rootNodeLinkStyle);
1691 else if (node.IsParentNode) {
1692 if (node.IsParentNode && parentNodeStyle != null) {
1693 style.CopyFrom (parentNodeLinkStyle);
1696 if (levelStyles != null && levelStyles.Count > level) {
1697 style.CopyFrom (levelLinkStyles [level]);
1699 if (nodeIsSelected) {
1700 style.CopyFrom (selectedNodeLinkStyle);
1702 style.AlwaysRenderTextDecoration = true;
1704 style.AddAttributesToRender (writer);
1707 void BeginNodeTag (HtmlTextWriter writer, TreeNode node, bool clientExpand)
1709 if(node.ToolTip.Length>0)
1710 writer.AddAttribute ("title", node.ToolTip);
1712 if (node.NavigateUrl != "") {
1713 string target = node.Target.Length > 0 ? node.Target : Target;
1715 string navUrl = ResolveClientUrl (node.NavigateUrl, String.Compare (target, "_blank", StringComparison.InvariantCultureIgnoreCase) != 0);
1717 string navUrl = ResolveClientUrl (node.NavigateUrl);
1719 writer.AddAttribute ("href", navUrl);
1720 if (target.Length > 0)
1721 writer.AddAttribute ("target", target);
1722 writer.RenderBeginTag (HtmlTextWriterTag.A);
1724 else if (node.SelectAction != TreeNodeSelectAction.None) {
1725 if (node.SelectAction == TreeNodeSelectAction.Expand && clientExpand)
1726 writer.AddAttribute ("href", GetClientExpandEvent (node));
1728 writer.AddAttribute ("href", GetClientEvent (node, "sel"));
1729 writer.RenderBeginTag (HtmlTextWriterTag.A);
1732 writer.RenderBeginTag (HtmlTextWriterTag.Span);
1735 string GetNodeImageToolTip (bool expand, string txt) {
1737 if (ExpandImageToolTip != "")
1738 return String.Format (ExpandImageToolTip, txt);
1739 else if (txt != null)
1740 return "Expand " + txt;
1742 return "Expand {0}";
1744 if (CollapseImageToolTip != "")
1745 return String.Format (CollapseImageToolTip, txt);
1746 else if (txt != null)
1747 return "Collapse " + txt;
1749 return "Collapse {0}";
1753 string GetNodeClientId (TreeNode node, string sufix)
1755 return ClientID + "_" + node.Path + (sufix != null ? "_" + sufix : "");
1758 string GetNodeImageUrl (string shape, ImageStyle imageStyle)
1761 if (!String.IsNullOrEmpty (LineImagesFolder))
1762 return ResolveClientUrl (LineImagesFolder + "/" + shape + ".gif");
1764 if (imageStyle != null) {
1765 if (shape == "plus") {
1766 if (!String.IsNullOrEmpty (imageStyle.Expand))
1767 return GetNodeIconUrl (imageStyle.Expand);
1769 else if (shape == "minus") {
1770 if (!String.IsNullOrEmpty (imageStyle.Collapse))
1771 return GetNodeIconUrl (imageStyle.Collapse);
1773 else if (shape == "noexpand") {
1774 if (!String.IsNullOrEmpty (imageStyle.NoExpand))
1775 return GetNodeIconUrl (imageStyle.NoExpand);
1779 if (shape == "plus") {
1780 if (!String.IsNullOrEmpty (ExpandImageUrl))
1781 return ResolveClientUrl (ExpandImageUrl);
1783 else if (shape == "minus") {
1784 if (!String.IsNullOrEmpty (CollapseImageUrl))
1785 return ResolveClientUrl (CollapseImageUrl);
1787 else if (shape == "noexpand") {
1788 if (!String.IsNullOrEmpty (NoExpandImageUrl))
1789 return ResolveClientUrl (NoExpandImageUrl);
1792 if (!String.IsNullOrEmpty (LineImagesFolder))
1793 return ResolveClientUrl (LineImagesFolder + "/" + shape + ".gif");
1795 return Page.ClientScript.GetWebResourceUrl (typeof (TreeView), "TreeView_" + shape + ".gif");
1798 string GetNodeIconUrl (string icon)
1800 return Page.ClientScript.GetWebResourceUrl (typeof (TreeView), icon + ".gif");
1803 string GetClientEvent (TreeNode node, string ev)
1805 return Page.ClientScript.GetPostBackClientHyperlink (this, ev + "|" + node.Path, true);
1808 string GetClientExpandEvent (TreeNode node)
1810 return "javascript:TreeView_ToggleExpand ('" + ClientID + "', '" + node.Path + "')";
1813 TreeNode FindNodeByPos (string path)
1815 string[] indexes = path.Split ('_');
1816 TreeNode node = null;
1818 foreach (string index in indexes) {
1819 int i = int.Parse (index);
1821 if (i >= Nodes.Count) return null;
1824 if (i >= node.ChildNodes.Count) return null;
1825 node = node.ChildNodes [i];
1831 void UnsetCheckStates (TreeNodeCollection col, NameValueCollection states)
1833 foreach (TreeNode node in col) {
1834 if (node.ShowCheckBoxInternal && node.Checked) {
1835 if (states == null || states [ClientID + "_cs_" + node.Path] == null)
1836 node.Checked = false;
1838 if (node.HasChildData)
1839 UnsetCheckStates (node.ChildNodes, states);
1843 void SetCheckStates (NameValueCollection states)
1848 string keyPrefix = ClientID + "_cs_";
1849 foreach (string key in states) {
1850 if (key.StartsWith (keyPrefix, StringComparison.Ordinal)) {
1851 string id = key.Substring (keyPrefix.Length);
1852 TreeNode node = FindNodeByPos (id);
1853 if (node != null && !node.Checked)
1854 node.Checked = true;
1859 void UnsetExpandStates (TreeNodeCollection col, string[] states)
1861 foreach (TreeNode node in col) {
1862 if (node.Expanded.HasValue && node.Expanded.Value) {
1863 bool expand = (Array.IndexOf (states, node.Path) != -1);
1864 if (!expand) node.Expanded = false;
1866 if (node.HasChildData)
1867 UnsetExpandStates (node.ChildNodes, states);
1871 void SetExpandStates (string[] states)
1873 foreach (string id in states) {
1874 if (id == null || id == "") continue;
1875 TreeNode node = FindNodeByPos (id);
1877 node.Expanded = true;
1881 string GetExpandStates ()
1883 StringBuilder sb = new StringBuilder ("|");
1885 foreach (TreeNode node in Nodes)
1886 GetExpandStates (sb, node);
1888 return sb.ToString ();
1891 void GetExpandStates (StringBuilder sb, TreeNode node)
1893 if (node.Expanded.HasValue && node.Expanded.Value) {
1894 sb.Append (node.Path);
1897 if (node.HasChildData) {
1898 foreach (TreeNode child in node.ChildNodes)
1899 GetExpandStates (sb, child);