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
56 TreeNodeStyle leafNodeStyle;
57 TreeNodeStyle nodeStyle;
58 TreeNodeStyle parentNodeStyle;
59 TreeNodeStyle rootNodeStyle;
60 TreeNodeStyle selectedNodeStyle;
62 TreeNodeStyleCollection levelStyles;
63 TreeNodeCollection nodes;
64 TreeNodeBindingCollection dataBindings;
66 TreeNode selectedNode;
69 int registeredStylesCounter = -1;
70 List<Style> levelLinkStyles;
71 Style controlLinkStyle;
73 Style rootNodeLinkStyle;
74 Style parentNodeLinkStyle;
75 Style leafNodeLinkStyle;
76 Style selectedNodeLinkStyle;
77 Style hoverNodeLinkStyle;
79 private static readonly object TreeNodeCheckChangedEvent = new object();
80 private static readonly object SelectedNodeChangedEvent = new object();
81 private static readonly object TreeNodeCollapsedEvent = new object();
82 private static readonly object TreeNodeDataBoundEvent = new object();
83 private static readonly object TreeNodeExpandedEvent = new object();
84 private static readonly object TreeNodePopulateEvent = new object();
86 static Hashtable imageStyles = new Hashtable ();
90 public ImageStyle (string expand, string collapse, string noExpand, string icon, string iconLeaf, string iconRoot) {
100 public string Collapse;
101 public string NoExpand;
102 public string RootIcon;
103 public string ParentIcon;
104 public string LeafIcon;
109 imageStyles [TreeViewImageSet.Arrows] = new ImageStyle ("arrow_plus", "arrow_minus", "arrow_noexpand", null, null, null);
110 imageStyles [TreeViewImageSet.BulletedList] = new ImageStyle (null, null, null, "dot_full", "dot_empty", "dot_full");
111 imageStyles [TreeViewImageSet.BulletedList2] = new ImageStyle (null, null, null, "box_full", "box_empty", "box_full");
112 imageStyles [TreeViewImageSet.BulletedList3] = new ImageStyle (null, null, null, "star_full", "star_empty", "star_full");
113 imageStyles [TreeViewImageSet.BulletedList4] = new ImageStyle (null, null, null, "star_full", "star_empty", "dots");
114 imageStyles [TreeViewImageSet.Contacts] = new ImageStyle ("TreeView_plus", "TreeView_minus", "contact", null, null, null);
115 imageStyles [TreeViewImageSet.Events] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, "warning", null);
116 imageStyles [TreeViewImageSet.Inbox] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", "inbox", "inbox", "inbox");
117 imageStyles [TreeViewImageSet.Msdn] = new ImageStyle ("box_plus", "box_minus", "box_noexpand", null, null, null);
118 imageStyles [TreeViewImageSet.Simple] = new ImageStyle ("TreeView_plus", "TreeView_minus", "box_full", null, null, null);
119 imageStyles [TreeViewImageSet.Simple2] = new ImageStyle ("TreeView_plus", "TreeView_minus", "box_empty", null, null, null);
122 imageStyles [TreeViewImageSet.News] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null);
123 imageStyles [TreeViewImageSet.Faq] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null);
124 imageStyles [TreeViewImageSet.WindowsHelp] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null);
125 imageStyles [TreeViewImageSet.XPFileExplorer] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null);
128 public event TreeNodeEventHandler TreeNodeCheckChanged {
129 add { Events.AddHandler (TreeNodeCheckChangedEvent, value); }
130 remove { Events.RemoveHandler (TreeNodeCheckChangedEvent, value); }
133 public event EventHandler SelectedNodeChanged {
134 add { Events.AddHandler (SelectedNodeChangedEvent, value); }
135 remove { Events.RemoveHandler (SelectedNodeChangedEvent, value); }
138 public event TreeNodeEventHandler TreeNodeCollapsed {
139 add { Events.AddHandler (TreeNodeCollapsedEvent, value); }
140 remove { Events.RemoveHandler (TreeNodeCollapsedEvent, value); }
143 public event TreeNodeEventHandler TreeNodeDataBound {
144 add { Events.AddHandler (TreeNodeDataBoundEvent, value); }
145 remove { Events.RemoveHandler (TreeNodeDataBoundEvent, value); }
148 public event TreeNodeEventHandler TreeNodeExpanded {
149 add { Events.AddHandler (TreeNodeExpandedEvent, value); }
150 remove { Events.RemoveHandler (TreeNodeExpandedEvent, value); }
153 public event TreeNodeEventHandler TreeNodePopulate {
154 add { Events.AddHandler (TreeNodePopulateEvent, value); }
155 remove { Events.RemoveHandler (TreeNodePopulateEvent, value); }
158 protected virtual void OnTreeNodeCheckChanged (TreeNodeEventArgs e)
160 if (Events != null) {
161 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeCheckChangedEvent];
162 if (eh != null) eh (this, e);
166 protected virtual void OnSelectedNodeChanged (EventArgs e)
168 if (Events != null) {
169 EventHandler eh = (EventHandler) Events [SelectedNodeChangedEvent];
170 if (eh != null) eh (this, e);
174 protected virtual void OnTreeNodeCollapsed (TreeNodeEventArgs e)
176 if (Events != null) {
177 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeCollapsedEvent];
178 if (eh != null) eh (this, e);
182 protected virtual void OnTreeNodeDataBound (TreeNodeEventArgs e)
184 if (Events != null) {
185 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeDataBoundEvent];
186 if (eh != null) eh (this, e);
190 protected virtual void OnTreeNodeExpanded (TreeNodeEventArgs e)
192 if (Events != null) {
193 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeExpandedEvent];
194 if (eh != null) eh (this, e);
198 protected virtual void OnTreeNodePopulate (TreeNodeEventArgs e)
200 if (Events != null) {
201 TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodePopulateEvent];
202 if (eh != null) eh (this, e);
208 public string CollapseImageToolTip {
210 return ViewState.GetString ("CollapseImageToolTip", "Collapse {0}");
213 ViewState["CollapseImageToolTip"] = value;
217 [MonoTODO ("Implement support for this")]
218 [WebCategory ("Behavior")]
219 [WebSysDescription ("Whether the tree will automatically generate bindings.")]
220 [DefaultValue (true)]
221 public bool AutoGenerateDataBindings {
223 return ViewState.GetBool ("AutoGenerateDataBindings", true);
226 ViewState["AutoGenerateDataBindings"] = value;
231 [WebSysDescription ("The url of the image to show when a node can be collapsed.")]
233 [WebCategory ("Appearance")]
234 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
235 public string CollapseImageUrl {
237 return ViewState.GetString ("CollapseImageUrl", "");
240 ViewState["CollapseImageUrl"] = value;
244 [WebCategory ("Data")]
245 [PersistenceMode (PersistenceMode.InnerProperty)]
246 [WebSysDescription ("Bindings for tree nodes.")]
247 [Editor ("System.Web.UI.Design.WebControls.TreeViewBindingsEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
248 [DefaultValue (null)]
249 [MergablePropertyAttribute (false)]
250 public TreeNodeBindingCollection DataBindings {
252 if (dataBindings == null) {
253 dataBindings = new TreeNodeBindingCollection ();
254 if (IsTrackingViewState)
255 ((IStateManager)dataBindings).TrackViewState();
261 [WebCategory ("Behavior")]
262 [WebSysDescription ("Whether the tree view can use client-side script to expand and collapse nodes.")]
264 [DefaultValue (true)]
265 public bool EnableClientScript {
267 return ViewState.GetBool ("EnableClientScript", true);
270 ViewState["EnableClientScript"] = value;
275 [WebCategory ("Behavior")]
276 [WebSysDescription ("The initial expand depth.")]
277 [TypeConverter ("System.Web.UI.WebControls.TreeView+TreeViewExpandDepthConverter, " + Consts.AssemblySystem_Web)]
278 public int ExpandDepth {
280 return ViewState.GetInt ("ExpandDepth", -1);
283 ViewState["ExpandDepth"] = value;
288 public string ExpandImageToolTip {
290 return ViewState.GetString ("ExpandImageToolTip", "Expand {0}");
293 ViewState["ExpandImageToolTip"] = value;
299 [WebSysDescription ("The url of the image to show when a node can be expanded.")]
300 [WebCategory ("Appearance")]
301 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
302 public string ExpandImageUrl {
304 return ViewState.GetString ("ExpandImageUrl", "");
307 ViewState["ExpandImageUrl"] = value;
311 [PersistenceMode (PersistenceMode.InnerProperty)]
312 [NotifyParentProperty (true)]
313 [DefaultValue (null)]
314 [WebCategory ("Styles")]
315 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
316 public Style HoverNodeStyle {
318 if (hoverNodeStyle == null) {
319 hoverNodeStyle = new Style();
320 if (IsTrackingViewState)
321 hoverNodeStyle.TrackViewState();
323 return hoverNodeStyle;
327 [DefaultValue (TreeViewImageSet.Custom)]
328 public TreeViewImageSet ImageSet {
330 return (TreeViewImageSet)ViewState.GetInt ("ImageSet", (int)TreeViewImageSet.Custom);
333 if (!Enum.IsDefined (typeof (TreeViewImageSet), value))
334 throw new ArgumentOutOfRangeException ();
335 ViewState["ImageSet"] = value;
339 [PersistenceMode (PersistenceMode.InnerProperty)]
340 [NotifyParentProperty (true)]
341 [DefaultValue (null)]
342 [WebCategory ("Styles")]
343 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
344 public TreeNodeStyle LeafNodeStyle {
346 if (leafNodeStyle == null) {
347 leafNodeStyle = new TreeNodeStyle ();
348 if (IsTrackingViewState)
349 leafNodeStyle.TrackViewState();
351 return leafNodeStyle;
355 [DefaultValue (null)]
356 [WebCategory ("Styles")]
357 [PersistenceMode (PersistenceMode.InnerProperty)]
358 [Editor ("System.Web.UI.Design.WebControls.TreeNodeStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
359 public TreeNodeStyleCollection LevelStyles {
361 if (levelStyles == null) {
362 levelStyles = new TreeNodeStyleCollection ();
363 if (IsTrackingViewState)
364 ((IStateManager)levelStyles).TrackViewState();
371 public string LineImagesFolder {
373 return ViewState.GetString ("LineImagesFolder", "");
376 ViewState["LineImagesFolder"] = value;
381 public int MaxDataBindDepth {
383 return ViewState.GetInt ("MaxDataBindDepth", -1);
386 ViewState["MaxDataBindDepth"] = value;
391 public int NodeIndent {
393 return ViewState.GetInt ("NodeIndent", 20);
396 ViewState["NodeIndent"] = value;
400 [PersistenceMode (PersistenceMode.InnerProperty)]
401 [Editor ("System.Web.UI.Design.WebControls.TreeNodeCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
402 [DefaultValueAttribute (null)]
403 [MergablePropertyAttribute (false)]
404 public TreeNodeCollection Nodes {
407 nodes = new TreeNodeCollection (this);
408 if (IsTrackingViewState)
409 ((IStateManager)nodes).TrackViewState();
415 [PersistenceMode (PersistenceMode.InnerProperty)]
416 [NotifyParentProperty (true)]
417 [DefaultValue (null)]
418 [WebCategory ("Styles")]
419 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
420 public TreeNodeStyle NodeStyle {
422 if (nodeStyle == null) {
423 nodeStyle = new TreeNodeStyle ();
424 if (IsTrackingViewState)
425 nodeStyle.TrackViewState();
431 [DefaultValue (false)]
432 public bool NodeWrap {
434 return ViewState.GetBool ("NodeWrap", false);
437 ViewState ["NodeWrap"] = value;
443 [WebSysDescription ("The url of the image to show for leaf nodes.")]
444 [WebCategory ("Appearance")]
445 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
446 public string NoExpandImageUrl {
448 return ViewState.GetString ("NoExpandImageUrl", "");
451 ViewState ["NoExpandImageUrl"] = value;
455 [PersistenceMode (PersistenceMode.InnerProperty)]
456 [NotifyParentProperty (true)]
457 [DefaultValue (null)]
458 [WebCategory ("Styles")]
459 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
460 public TreeNodeStyle ParentNodeStyle {
462 if (parentNodeStyle == null) {
463 parentNodeStyle = new TreeNodeStyle ();
464 if (IsTrackingViewState)
465 parentNodeStyle.TrackViewState();
467 return parentNodeStyle;
472 public char PathSeparator {
474 return ViewState.GetChar ("PathSeparator", '/');
477 ViewState ["PathSeparator"] = value;
481 [DefaultValue (true)]
482 public bool PopulateNodesFromClient {
484 return ViewState.GetBool ("PopulateNodesFromClient", true);
487 ViewState ["PopulateNodesFromClient"] = value;
491 [PersistenceMode (PersistenceMode.InnerProperty)]
492 [NotifyParentProperty (true)]
493 [DefaultValue (null)]
494 [WebCategory ("Styles")]
495 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
496 public TreeNodeStyle RootNodeStyle {
498 if (rootNodeStyle == null) {
499 rootNodeStyle = new TreeNodeStyle ();
500 if (IsTrackingViewState)
501 rootNodeStyle.TrackViewState();
503 return rootNodeStyle;
507 [PersistenceMode (PersistenceMode.InnerProperty)]
508 [NotifyParentProperty (true)]
509 [DefaultValue (null)]
510 [WebCategory ("Styles")]
511 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
512 public TreeNodeStyle SelectedNodeStyle {
514 if (selectedNodeStyle == null) {
515 selectedNodeStyle = new TreeNodeStyle ();
516 if (IsTrackingViewState)
517 selectedNodeStyle.TrackViewState();
519 return selectedNodeStyle;
523 private Style ControlLinkStyle {
525 if (controlLinkStyle == null) {
526 controlLinkStyle = new Style ();
527 controlLinkStyle.AlwaysRenderTextDecoration = true;
529 return controlLinkStyle;
533 private Style NodeLinkStyle {
535 if (nodeLinkStyle == null) {
536 nodeLinkStyle = new Style ();
538 return nodeLinkStyle;
542 private Style RootNodeLinkStyle {
544 if (rootNodeLinkStyle == null) {
545 rootNodeLinkStyle = new Style ();
547 return rootNodeLinkStyle;
551 private Style ParentNodeLinkStyle {
553 if (parentNodeLinkStyle == null) {
554 parentNodeLinkStyle = new Style ();
556 return parentNodeLinkStyle;
560 private Style SelectedNodeLinkStyle {
562 if (selectedNodeLinkStyle == null) {
563 selectedNodeLinkStyle = new Style ();
565 return selectedNodeLinkStyle;
569 private Style LeafNodeLinkStyle {
571 if (leafNodeLinkStyle == null) {
572 leafNodeLinkStyle = new Style ();
574 return leafNodeLinkStyle;
578 private Style HoverNodeLinkStyle {
580 if (hoverNodeLinkStyle == null) {
581 hoverNodeLinkStyle = new Style ();
583 return hoverNodeLinkStyle;
587 [DefaultValue (TreeNodeTypes.None)]
588 public TreeNodeTypes ShowCheckBoxes {
590 return (TreeNodeTypes)ViewState.GetInt ("ShowCheckBoxes", (int)TreeNodeTypes.None);
594 throw new ArgumentOutOfRangeException ();
595 ViewState ["ShowCheckBoxes"] = value;
599 [DefaultValue (true)]
600 public bool ShowExpandCollapse {
602 return ViewState.GetBool ("ShowExpandCollapse", true);
605 ViewState ["ShowExpandCollapse"] = value;
609 [DefaultValue (false)]
610 public bool ShowLines {
612 return ViewState.GetBool ("ShowLines", false);
615 ViewState ["ShowLines"] = value;
620 public string SkipLinkText
623 return ViewState.GetString ("SkipLinkText", "Skip Navigation Links.");
626 ViewState ["SkipLinkText"] = value;
632 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
633 public TreeNode SelectedNode {
634 get { return selectedNode; }
639 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
640 public string SelectedValue {
641 get { return selectedNode != null ? selectedNode.Value : ""; }
645 public string Target {
647 return ViewState.GetString ("Target", "");
650 ViewState ["Target"] = value;
654 [MonoTODO ("why override?")]
655 public override bool Visible
661 base.Visible = value;
666 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
667 public TreeNodeCollection CheckedNodes {
669 TreeNodeCollection col = new TreeNodeCollection ();
670 FindCheckedNodes (Nodes, col);
675 void FindCheckedNodes (TreeNodeCollection nodeList, TreeNodeCollection result)
677 foreach (TreeNode node in nodeList) {
678 if (node.Checked) result.Add (node);
679 FindCheckedNodes (node.ChildNodes, result);
683 public void ExpandAll ()
685 foreach (TreeNode node in Nodes)
689 public void CollapseAll ()
691 foreach (TreeNode node in Nodes)
695 public TreeNode FindNode (string valuePath)
697 if (valuePath == null) throw new ArgumentNullException ("valuePath");
698 string[] path = valuePath.Split (PathSeparator);
700 TreeNodeCollection col = Nodes;
701 bool foundBranch = true;
702 while (col.Count > 0 && foundBranch) {
704 foreach (TreeNode node in col) {
705 if (node.Value == path [n]) {
706 if (++n == path.Length) return node;
707 col = node.ChildNodes;
716 ImageStyle GetImageStyle ()
718 if (ImageSet != TreeViewImageSet.Custom)
719 return (ImageStyle) imageStyles [ImageSet];
724 protected override HtmlTextWriterTag TagKey {
725 get { return HtmlTextWriterTag.Div; }
728 protected internal virtual TreeNode CreateNode ()
730 return new TreeNode (this);
733 public sealed override void DataBind ()
738 protected void SetNodeDataBound (TreeNode node, bool dataBound)
740 node.SetDataBound (dataBound);
743 protected void SetNodeDataPath (TreeNode node, string dataPath)
745 node.SetDataPath (dataPath);
748 protected void SetNodeDataItem (TreeNode node, object dataItem)
750 node.SetDataItem (dataItem);
753 protected internal override void OnInit (EventArgs e)
758 internal void SetSelectedNode (TreeNode node, bool loading)
760 if (selectedNode == node) return;
761 if (selectedNode != null)
762 selectedNode.SelectedFlag = false;
764 selectedNode.SelectedFlag = true;
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));
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) {
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 string[] args = eventArgument.Split ('|');
874 TreeNode node = FindNodeByPos (args[1]);
875 if (node == null) return;
877 if (args [0] == "sel")
878 HandleSelectEvent (node);
879 else if (args [0] == "ec")
880 HandleExpandCollapseEvent (node);
883 void HandleSelectEvent (TreeNode node)
885 switch (node.SelectAction) {
886 case TreeNodeSelectAction.Select:
889 case TreeNodeSelectAction.Expand:
892 case TreeNodeSelectAction.SelectExpand:
899 void HandleExpandCollapseEvent (TreeNode node)
901 node.ToggleExpandState ();
904 protected virtual void RaisePostDataChangedEvent ()
908 string callbackResult;
909 protected virtual void RaiseCallbackEvent (string eventArgs)
911 RequiresDataBinding = true;
914 TreeNode node = FindNodeByPos (eventArgs);
915 ArrayList levelLines = new ArrayList ();
918 int childCount = nd.Parent != null ? nd.Parent.ChildNodes.Count : Nodes.Count;
919 levelLines.Insert (0, (nd.Index < childCount - 1) ? this : null);
923 StringWriter sw = new StringWriter ();
924 HtmlTextWriter writer = new HtmlTextWriter (sw);
925 EnsureStylesPrepared ();
927 node.Expanded = true;
928 int num = node.ChildNodes.Count;
929 for (int n=0; n<num; n++)
930 RenderNode (writer, node.ChildNodes [n], node.Depth + 1, levelLines, true, n<num-1);
932 string res = sw.ToString ();
933 callbackResult = res != "" ? res : "*";
936 protected virtual string GetCallbackResult ()
938 return callbackResult;
941 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
943 RaisePostBackEvent (eventArgument);
946 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
948 return LoadPostData (postDataKey, postCollection);
951 void IPostBackDataHandler.RaisePostDataChangedEvent ()
953 RaisePostDataChangedEvent ();
956 void ICallbackEventHandler.RaiseCallbackEvent (string eventArgs)
958 RaiseCallbackEvent (eventArgs);
961 string ICallbackEventHandler.GetCallbackResult ()
963 return GetCallbackResult ();
966 protected override ControlCollection CreateControlCollection ()
968 return new EmptyControlCollection (this);
971 protected internal override void PerformDataBinding ()
973 base.PerformDataBinding ();
974 InitializeDataBindings ();
975 HierarchicalDataSourceView data = GetData ("");
979 IHierarchicalEnumerable e = data.Select ();
980 FillBoundChildrenRecursive (e, Nodes);
983 private void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, TreeNodeCollection nodeCollection) {
984 foreach (object obj in hEnumerable) {
985 IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
986 TreeNode child = new TreeNode ();
987 nodeCollection.Add (child);
989 OnTreeNodeDataBound (new TreeNodeEventArgs (child));
991 if (MaxDataBindDepth >= 0 && child.Depth == MaxDataBindDepth)
994 if (hdata == null || !hdata.HasChildren)
997 IHierarchicalEnumerable e = hdata.GetChildren ();
998 FillBoundChildrenRecursive (e, child.ChildNodes);
1002 protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection)
1006 if (EnableClientScript && PopulateNodesFromClient) {
1007 string states = postCollection [ClientID + "_PopulatedStates"];
1008 if (states != null) {
1009 foreach (string id in states.Split ('|')) {
1010 if (String.IsNullOrEmpty(id))
1012 TreeNode node = FindNodeByPos (id);
1013 if (node != null && node.PopulateOnDemand && !node.Populated)
1020 if (ShowCheckBoxes != TreeNodeTypes.None) {
1021 UnsetCheckStates (Nodes, postCollection);
1022 SetCheckStates (postCollection);
1026 if (EnableClientScript) {
1027 string states = postCollection [ClientID + "_ExpandStates"];
1028 if (states != null) {
1029 string[] ids = states.Split ('|');
1030 UnsetExpandStates (Nodes, ids);
1031 SetExpandStates (ids);
1034 UnsetExpandStates (Nodes, new string[0]);
1040 protected internal override void OnPreRender (EventArgs e)
1042 base.OnPreRender (e);
1046 Page.RegisterRequiresPostBack (this);
1048 if (EnableClientScript && !Page.ClientScript.IsClientScriptIncludeRegistered (typeof(TreeView), "TreeView.js")) {
1049 string url = Page.ClientScript.GetWebResourceUrl (typeof(TreeView), "TreeView.js");
1050 Page.ClientScript.RegisterClientScriptInclude (typeof(TreeView), "TreeView.js", url);
1054 string ctree = ClientID + "_data";
1055 string script = string.Format ("var {0} = new Object ();\n", ctree);
1056 script += string.Format ("{0}.showImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (ShowExpandCollapse));
1058 if (ShowExpandCollapse) {
1059 bool defaultImages = ShowLines || ImageSet != TreeViewImageSet.Custom || (ExpandImageUrl == "" && CollapseImageUrl == "");
1060 script += string.Format ("{0}.defaultImages = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (defaultImages));
1061 ImageStyle imageStyle = GetImageStyle ();
1062 if (!defaultImages) {
1063 script += string.Format ("{0}.expandImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("plus", imageStyle)));
1064 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}.populateFromClient = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (PopulateNodesFromClient));
1072 script += string.Format ("{0}.expandAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (true, null)));
1073 script += string.Format ("{0}.collapseAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (false, null)));
1075 if (!Page.IsPostBack) {
1076 SetNodesExpandedToDepthRecursive (Nodes);
1079 if (EnableClientScript) {
1080 Page.ClientScript.RegisterHiddenField (ClientID + "_ExpandStates", GetExpandStates ());
1082 // Make sure the basic script infrastructure is rendered
1083 Page.ClientScript.GetCallbackEventReference (this, "null", "", "null");
1084 Page.ClientScript.GetPostBackClientHyperlink (this, "");
1087 if (EnableClientScript && PopulateNodesFromClient) {
1088 Page.ClientScript.RegisterHiddenField (ClientID + "_PopulatedStates", "|");
1091 EnsureStylesPrepared ();
1093 if (hoverNodeStyle != null) {
1094 if (Page.Header == null)
1095 throw new InvalidOperationException ("Using TreeView.HoverNodeStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
1096 RegisterStyle (HoverNodeStyle, HoverNodeLinkStyle);
1097 script += string.Format ("{0}.hoverClass = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (HoverNodeStyle.RegisteredCssClass));
1098 script += string.Format ("{0}.hoverLinkClass = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (HoverNodeLinkStyle.RegisteredCssClass));
1101 Page.ClientScript.RegisterStartupScript (typeof(TreeView), this.UniqueID, script, true);
1105 void EnsureStylesPrepared () {
1108 stylesPrepared = true;
1112 private void PrepareStyles () {
1113 // The order in which styles are defined matters when more than one class
1114 // is assigned to an element
1115 ControlLinkStyle.CopyTextStylesFrom (ControlStyle);
1116 RegisterStyle (ControlLinkStyle);
1118 if (nodeStyle != null)
1119 RegisterStyle (NodeStyle, NodeLinkStyle);
1121 if (rootNodeStyle != null)
1122 RegisterStyle (RootNodeStyle, RootNodeLinkStyle);
1124 if (parentNodeStyle != null)
1125 RegisterStyle (ParentNodeStyle, ParentNodeLinkStyle);
1127 if (leafNodeStyle != null)
1128 RegisterStyle (LeafNodeStyle, LeafNodeLinkStyle);
1131 if (levelStyles != null) {
1132 levelLinkStyles = new List<Style> ();
1133 foreach (Style style in levelStyles) {
1134 Style linkStyle = new Style ();
1135 levelLinkStyles.Add (linkStyle);
1136 RegisterStyle (style, linkStyle);
1140 if (selectedNodeStyle != null)
1141 RegisterStyle (SelectedNodeStyle, SelectedNodeLinkStyle);
1144 void SetNodesExpandedToDepthRecursive (TreeNodeCollection nodes) {
1145 foreach (TreeNode node in nodes) {
1146 if (!node.Expanded.HasValue) {
1147 if (ExpandDepth < 0 || node.Depth < ExpandDepth)
1148 node.Expanded = true;
1150 SetNodesExpandedToDepthRecursive (node.ChildNodes);
1154 string IncrementStyleClassName () {
1155 registeredStylesCounter++;
1156 return ClientID + "_" + registeredStylesCounter;
1159 void RegisterStyle (Style baseStyle, Style linkStyle) {
1160 linkStyle.CopyTextStylesFrom (baseStyle);
1161 linkStyle.BorderStyle = BorderStyle.None;
1162 baseStyle.Font.Reset ();
1163 RegisterStyle (linkStyle);
1164 RegisterStyle (baseStyle);
1167 void RegisterStyle (Style baseStyle) {
1168 if (Page.Header == null)
1170 string className = IncrementStyleClassName ();
1171 baseStyle.SetRegisteredCssClass (className);
1172 Page.Header.StyleSheet.CreateStyleRule (baseStyle, this, "." + className);
1175 string GetBindingKey (string dataMember, int depth)
1177 return dataMember + " " + depth;
1180 void InitializeDataBindings () {
1181 if (dataBindings != null && dataBindings.Count > 0) {
1182 bindings = new Hashtable ();
1183 foreach (TreeNodeBinding bin in dataBindings) {
1184 string key = GetBindingKey (bin.DataMember, bin.Depth);
1185 bindings [key] = bin;
1192 internal TreeNodeBinding FindBindingForNode (string type, int depth)
1194 if (bindings == null)
1197 TreeNodeBinding bin = (TreeNodeBinding) bindings [GetBindingKey (type, depth)];
1198 if (bin != null) return bin;
1200 bin = (TreeNodeBinding) bindings [GetBindingKey (type, -1)];
1201 if (bin != null) return bin;
1203 bin = (TreeNodeBinding) bindings [GetBindingKey ("", depth)];
1204 if (bin != null) return bin;
1206 return (TreeNodeBinding) bindings [GetBindingKey ("", -1)];
1209 internal void DecorateNode(TreeNode node)
1214 if (node.ImageUrl != null && node.ImageUrl.Length > 0)
1217 if (node.IsRootNode && rootNodeStyle != null) {
1218 node.ImageUrl = rootNodeStyle.ImageUrl;
1221 if (node.IsParentNode && parentNodeStyle != null) {
1222 node.ImageUrl = parentNodeStyle.ImageUrl;
1225 if (node.IsLeafNode && leafNodeStyle != null)
1226 node.ImageUrl = leafNodeStyle.ImageUrl;
1229 protected internal override void RenderContents (HtmlTextWriter writer)
1231 ArrayList levelLines = new ArrayList ();
1232 int num = Nodes.Count;
1233 for (int n=0; n<num; n++)
1234 RenderNode (writer, Nodes [n], 0, levelLines, n>0, n<num-1);
1237 protected override void AddAttributesToRender(HtmlTextWriter writer)
1239 base.AddAttributesToRender (writer);
1242 public override void RenderBeginTag (HtmlTextWriter writer)
1244 if (SkipLinkText != "") {
1245 writer.AddAttribute (HtmlTextWriterAttribute.Href, "#" + ClientID + "_SkipLink");
1246 writer.RenderBeginTag (HtmlTextWriterTag.A);
1248 Image img = new Image ();
1249 ClientScriptManager csm = new ClientScriptManager (null);
1250 img.ImageUrl = csm.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif");
1251 img.Attributes.Add ("height", "0");
1252 img.Attributes.Add ("width", "0");
1253 img.AlternateText = SkipLinkText;
1254 img.Render (writer);
1256 writer.RenderEndTag ();
1258 base.RenderBeginTag (writer);
1261 public override void RenderEndTag (HtmlTextWriter writer)
1263 base.RenderEndTag (writer);
1265 if (SkipLinkText != "") {
1266 writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID + "_SkipLink");
1267 writer.RenderBeginTag (HtmlTextWriterTag.A);
1268 writer.RenderEndTag ();
1272 void RenderNode (HtmlTextWriter writer, TreeNode node, int level, ArrayList levelLines, bool hasPrevious, bool hasNext)
1277 bool clientExpand = EnableClientScript && Events [TreeNodeCollapsedEvent] == null && Events [TreeNodeExpandedEvent] == null;
1278 ImageStyle imageStyle = GetImageStyle ();
1279 bool renderChildNodes = node.Expanded.HasValue && node.Expanded.Value;
1281 if (clientExpand && !renderChildNodes)
1282 renderChildNodes = (!node.PopulateOnDemand || node.Populated);
1286 if (renderChildNodes)
1287 hasChildNodes = node.ChildNodes.Count > 0;
1289 hasChildNodes = (node.PopulateOnDemand && !node.Populated) || node.ChildNodes.Count > 0;
1291 writer.AddAttribute ("cellpadding", "0");
1292 writer.AddAttribute ("cellspacing", "0");
1293 writer.AddStyleAttribute ("border-width", "0");
1294 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1296 Unit nodeSpacing = GetNodeSpacing (node);
1298 if (nodeSpacing != Unit.Empty && (node.Depth > 0 || node.Index > 0))
1299 RenderMenuItemSpacing (writer, nodeSpacing);
1301 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1303 // Vertical lines from previous levels
1305 nodeImage = GetNodeImageUrl ("i", imageStyle);
1306 for (int n=0; n<level; n++) {
1307 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1308 writer.AddStyleAttribute ("width", NodeIndent + "px");
1309 writer.AddStyleAttribute ("height", "1px");
1310 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1311 if (ShowLines && levelLines [n] != null) {
1312 writer.AddAttribute ("src", nodeImage);
1313 writer.AddAttribute (HtmlTextWriterAttribute.Alt, "");
1314 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1315 writer.RenderEndTag ();
1317 writer.RenderEndTag ();
1318 writer.RenderEndTag (); // TD
1321 // Node image + line
1323 if (ShowExpandCollapse || ShowLines) {
1324 bool buttonImage = false;
1325 string tooltip = "";
1329 if (hasPrevious && hasNext) shape = "t";
1330 else if (hasPrevious && !hasNext) shape = "l";
1331 else if (!hasPrevious && hasNext) shape = "r";
1332 else shape = "dash";
1335 if (ShowExpandCollapse) {
1336 if (hasChildNodes) {
1338 if (node.Expanded.HasValue && node.Expanded.Value) shape += "minus";
1339 else shape += "plus";
1340 tooltip = GetNodeImageToolTip (!(node.Expanded.HasValue && node.Expanded.Value), node.Text);
1341 } else if (!ShowLines)
1346 nodeImage = GetNodeImageUrl (shape, imageStyle);
1347 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1350 if (!clientExpand || (!PopulateNodesFromClient && node.PopulateOnDemand && !node.Populated))
1351 writer.AddAttribute ("href", GetClientEvent (node, "ec"));
1353 writer.AddAttribute ("href", GetClientExpandEvent(node));
1354 writer.RenderBeginTag (HtmlTextWriterTag.A); // Anchor
1357 writer.AddAttribute ("alt", tooltip);
1359 if (buttonImage && clientExpand)
1360 writer.AddAttribute ("id", GetNodeClientId (node, "img"));
1361 writer.AddAttribute ("src", nodeImage);
1363 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
1364 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1365 writer.RenderEndTag ();
1368 writer.RenderEndTag (); // Anchor
1370 writer.RenderEndTag (); // TD
1376 string imageUrl = node.ImageUrl;
1377 if (imageUrl == "" && imageStyle != null) {
1378 if (imageStyle.RootIcon != null && node.IsRootNode)
1379 imageUrl = GetNodeIconUrl (imageStyle.RootIcon);
1380 else if (imageStyle.ParentIcon != null && node.IsParentNode)
1381 imageUrl = GetNodeIconUrl (imageStyle.ParentIcon);
1382 else if (imageStyle.LeafIcon != null && node.IsLeafNode)
1383 imageUrl = GetNodeIconUrl (imageStyle.LeafIcon);
1386 if (imageUrl != "") {
1387 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1388 BeginNodeTag (writer, node, clientExpand);
1389 writer.AddAttribute ("src", imageUrl);
1390 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
1391 writer.AddAttribute ("alt", node.ImageToolTip);
1392 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1393 writer.RenderEndTag (); // IMG
1394 writer.RenderEndTag (); // style tag
1395 writer.RenderEndTag (); // TD
1399 writer.AddStyleAttribute ("white-space", "nowrap");
1400 AddNodeStyle (writer, node, level);
1401 if (EnableClientScript) {
1402 writer.AddAttribute ("onmouseout", "TreeView_UnhoverNode(this)");
1403 writer.AddAttribute ("onmouseover", "TreeView_HoverNode('" + ClientID + "', this)");
1405 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1410 if (node.ShowCheckBox.HasValue)
1411 showChecks = node.ShowCheckBox.Value;
1413 showChecks = (ShowCheckBoxes == TreeNodeTypes.All) ||
1414 ((ShowCheckBoxes & TreeNodeTypes.Leaf) > 0 && node.IsLeafNode) ||
1415 ((ShowCheckBoxes & TreeNodeTypes.Parent) > 0 && node.IsParentNode && node.Parent != null) ||
1416 ((ShowCheckBoxes & TreeNodeTypes.Root) > 0 && node.Parent == null && node.ChildNodes.Count > 0);
1419 writer.AddAttribute ("name", ClientID + "_cs_" + node.Path);
1420 writer.AddAttribute ("type", "checkbox");
1421 writer.AddAttribute ("title", node.Text);
1422 if (node.Checked) writer.AddAttribute ("checked", "checked");
1423 writer.RenderBeginTag (HtmlTextWriterTag.Input); // INPUT
1424 writer.RenderEndTag (); // INPUT
1429 node.BeginRenderText (writer);
1432 writer.AddAttribute ("id", GetNodeClientId (node, "txt"));
1433 AddNodeLinkStyle (writer, node, level);
1434 BeginNodeTag (writer, node, clientExpand);
1435 writer.Write (node.Text);
1436 writer.RenderEndTag (); // style tag
1438 node.EndRenderText (writer);
1440 writer.RenderEndTag (); // TD
1442 writer.RenderEndTag (); // TR
1444 if (nodeSpacing != Unit.Empty)
1445 RenderMenuItemSpacing (writer, nodeSpacing);
1447 writer.RenderEndTag (); // TABLE
1453 if (level >= levelLines.Count) {
1454 if (hasNext) levelLines.Add (this);
1455 else levelLines.Add (null);
1457 if (hasNext) levelLines [level] = this;
1458 else levelLines [level] = null;
1462 if (!(node.Expanded.HasValue && node.Expanded.Value)) writer.AddStyleAttribute ("display", "none");
1463 else writer.AddStyleAttribute ("display", "block");
1464 writer.AddAttribute ("id", GetNodeClientId (node, null));
1465 writer.RenderBeginTag (HtmlTextWriterTag.Span);
1467 if (renderChildNodes) {
1468 int num = node.ChildNodes.Count;
1469 for (int n=0; n<num; n++)
1470 RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
1472 writer.RenderEndTag (); // SPAN
1474 else if (renderChildNodes) {
1475 int num = node.ChildNodes.Count;
1476 for (int n=0; n<num; n++)
1477 RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
1482 private void RenderMenuItemSpacing (HtmlTextWriter writer, Unit itemSpacing) {
1483 writer.AddStyleAttribute ("height", itemSpacing.ToString ());
1484 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1485 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1486 writer.RenderEndTag ();
1487 writer.RenderEndTag ();
1490 private Unit GetNodeSpacing (TreeNode node) {
1491 if (node.Selected && selectedNodeStyle != null && selectedNodeStyle.NodeSpacing != Unit.Empty) {
1492 return selectedNodeStyle.NodeSpacing;
1495 if (levelStyles != null && node.Depth < levelStyles.Count && levelStyles [node.Depth].NodeSpacing != Unit.Empty) {
1496 return levelStyles [node.Depth].NodeSpacing;
1499 if (node.IsLeafNode) {
1500 if (leafNodeStyle != null && leafNodeStyle.NodeSpacing != Unit.Empty)
1501 return leafNodeStyle.NodeSpacing;
1503 else if (node.IsRootNode) {
1504 if (rootNodeStyle != null && rootNodeStyle.NodeSpacing != Unit.Empty)
1505 return rootNodeStyle.NodeSpacing;
1507 else if (node.IsParentNode) {
1508 if (parentNodeStyle != null && parentNodeStyle.NodeSpacing != Unit.Empty)
1509 return parentNodeStyle.NodeSpacing;
1512 if (nodeStyle != null)
1513 return nodeStyle.NodeSpacing;
1518 void AddNodeStyle (HtmlTextWriter writer, TreeNode node, int level)
1520 TreeNodeStyle style = new TreeNodeStyle ();
1521 if (Page.Header != null) {
1522 // styles are registered
1523 if (nodeStyle != null) {
1524 style.AddCssClass (nodeStyle.CssClass);
1525 style.AddCssClass (nodeStyle.RegisteredCssClass);
1527 if (node.IsLeafNode) {
1528 if (leafNodeStyle != null) {
1529 style.AddCssClass (leafNodeStyle.CssClass);
1530 style.AddCssClass (leafNodeStyle.RegisteredCssClass);
1533 else if (node.IsRootNode) {
1534 if (rootNodeStyle != null) {
1535 style.AddCssClass (rootNodeStyle.CssClass);
1536 style.AddCssClass (rootNodeStyle.RegisteredCssClass);
1539 else if (node.IsParentNode) {
1540 if (parentNodeStyle != null) {
1541 style.AddCssClass (parentNodeStyle.CssClass);
1542 style.AddCssClass (parentNodeStyle.RegisteredCssClass);
1545 if (levelStyles != null && levelStyles.Count > level) {
1546 style.AddCssClass (levelStyles [level].CssClass);
1547 style.AddCssClass (levelStyles [level].RegisteredCssClass);
1549 if (node == SelectedNode && selectedNodeStyle != null) {
1550 style.AddCssClass (selectedNodeStyle.CssClass);
1551 style.AddCssClass (selectedNodeStyle.RegisteredCssClass);
1555 // styles are not registered
1556 if (nodeStyle != null) {
1557 style.CopyFrom (nodeStyle);
1559 if (node.IsLeafNode) {
1560 if (leafNodeStyle != null) {
1561 style.CopyFrom (leafNodeStyle);
1564 else if (node.IsRootNode) {
1565 if (rootNodeStyle != null) {
1566 style.CopyFrom (rootNodeStyle);
1569 else if (node.IsParentNode) {
1570 if (parentNodeStyle != null) {
1571 style.CopyFrom (parentNodeStyle);
1574 if (levelStyles != null && levelStyles.Count > level) {
1575 style.CopyFrom (levelStyles [level]);
1577 if (node == SelectedNode && selectedNodeStyle != null) {
1578 style.CopyFrom (selectedNodeStyle);
1581 style.AddAttributesToRender (writer);
1584 void AddNodeLinkStyle (HtmlTextWriter writer, TreeNode node, int level) {
1585 Style style = new Style ();
1586 if (Page.Header != null) {
1587 // styles are registered
1588 style.AddCssClass (ControlLinkStyle.RegisteredCssClass);
1590 if (nodeStyle != null) {
1591 style.AddCssClass (nodeLinkStyle.CssClass);
1592 style.AddCssClass (nodeLinkStyle.RegisteredCssClass);
1594 if (node.IsLeafNode) {
1595 if (leafNodeStyle != null) {
1596 style.AddCssClass (leafNodeLinkStyle.CssClass);
1597 style.AddCssClass (leafNodeLinkStyle.RegisteredCssClass);
1600 else if (node.IsRootNode) {
1601 if (rootNodeStyle != null) {
1602 style.AddCssClass (rootNodeLinkStyle.CssClass);
1603 style.AddCssClass (rootNodeLinkStyle.RegisteredCssClass);
1606 else if (node.IsParentNode) {
1607 if (parentNodeStyle != null) {
1608 style.AddCssClass (parentNodeLinkStyle.CssClass);
1609 style.AddCssClass (parentNodeLinkStyle.RegisteredCssClass);
1612 if (levelStyles != null && levelStyles.Count > level) {
1613 style.AddCssClass (levelLinkStyles [level].CssClass);
1614 style.AddCssClass (levelLinkStyles [level].RegisteredCssClass);
1616 if (node == SelectedNode && selectedNodeStyle != null) {
1617 style.AddCssClass (selectedNodeLinkStyle.CssClass);
1618 style.AddCssClass (selectedNodeLinkStyle.RegisteredCssClass);
1622 // styles are not registered
1623 style.CopyFrom (ControlLinkStyle);
1624 if (nodeStyle != null) {
1625 style.CopyFrom (nodeLinkStyle);
1627 if (node.IsLeafNode) {
1628 if (node.IsLeafNode && leafNodeStyle != null) {
1629 style.CopyFrom (leafNodeLinkStyle);
1632 else if (node.IsRootNode) {
1633 if (node.IsRootNode && rootNodeStyle != null) {
1634 style.CopyFrom (rootNodeLinkStyle);
1637 else if (node.IsParentNode) {
1638 if (node.IsParentNode && parentNodeStyle != null) {
1639 style.CopyFrom (parentNodeLinkStyle);
1642 if (levelStyles != null && levelStyles.Count > level) {
1643 style.CopyFrom (levelLinkStyles [level]);
1645 if (node == SelectedNode && selectedNodeStyle != null) {
1646 style.CopyFrom (selectedNodeLinkStyle);
1648 style.AlwaysRenderTextDecoration = true;
1650 style.AddAttributesToRender (writer);
1653 void BeginNodeTag (HtmlTextWriter writer, TreeNode node, bool clientExpand)
1655 if(node.ToolTip.Length>0)
1656 writer.AddAttribute ("title", node.ToolTip);
1658 if (node.NavigateUrl != "") {
1659 writer.AddAttribute ("href", node.NavigateUrl);
1660 if (node.Target.Length > 0)
1661 writer.AddAttribute ("target", node.Target);
1662 else if (Target.Length > 0)
1663 writer.AddAttribute ("target", Target);
1664 writer.RenderBeginTag (HtmlTextWriterTag.A);
1666 else if (node.SelectAction != TreeNodeSelectAction.None) {
1667 if (node.SelectAction == TreeNodeSelectAction.Expand && clientExpand)
1668 writer.AddAttribute ("href", GetClientExpandEvent (node));
1670 writer.AddAttribute ("href", GetClientEvent (node, "sel"));
1671 writer.RenderBeginTag (HtmlTextWriterTag.A);
1674 writer.RenderBeginTag (HtmlTextWriterTag.Span);
1677 string GetNodeImageToolTip (bool expand, string txt) {
1679 if (ExpandImageToolTip != "")
1680 return String.Format (ExpandImageToolTip, txt);
1681 else if (txt != null)
1682 return "Expand " + txt;
1684 return "Expand {0}";
1686 if (CollapseImageToolTip != "")
1687 return String.Format (CollapseImageToolTip, txt);
1688 else if (txt != null)
1689 return "Collapse " + txt;
1691 return "Collapse {0}";
1695 string GetNodeClientId (TreeNode node, string sufix)
1697 return ClientID + "_" + node.Path + (sufix != null ? "_" + sufix : "");
1700 string GetNodeImageUrl (string shape, ImageStyle imageStyle)
1703 if (LineImagesFolder != "")
1704 return LineImagesFolder + "/" + shape + ".gif";
1706 if (shape == "plus") {
1707 if (ExpandImageUrl != "")
1708 return ExpandImageUrl;
1709 if (imageStyle != null && imageStyle.Expand != null)
1710 return imageStyle.Expand;
1712 else if (shape == "minus") {
1713 if (CollapseImageUrl != "")
1714 return CollapseImageUrl;
1715 if (imageStyle != null && imageStyle.Collapse != null)
1716 return imageStyle.Collapse;
1718 else if (shape == "noexpand") {
1719 if (NoExpandImageUrl != "")
1720 return NoExpandImageUrl;
1721 if (imageStyle != null && imageStyle.NoExpand != null)
1722 return imageStyle.NoExpand;
1725 return AssemblyResourceLoader.GetResourceUrl (typeof(TreeView), "TreeView_" + shape + ".gif");
1728 string GetNodeIconUrl (string icon)
1730 return AssemblyResourceLoader.GetResourceUrl (typeof(TreeView), icon + ".gif");
1733 string GetClientEvent (TreeNode node, string ev)
1735 return Page.ClientScript.GetPostBackClientHyperlink (this, ev + "|" + node.Path);
1738 string GetClientExpandEvent (TreeNode node)
1740 return "javascript:TreeView_ToggleExpand ('" + ClientID + "', '" + node.Path + "')";
1743 TreeNode FindNodeByPos (string path)
1745 string[] indexes = path.Split ('_');
1746 TreeNode node = null;
1748 foreach (string index in indexes) {
1749 int i = int.Parse (index);
1751 if (i >= Nodes.Count) return null;
1754 if (i >= node.ChildNodes.Count) return null;
1755 node = node.ChildNodes [i];
1761 void UnsetCheckStates (TreeNodeCollection col, NameValueCollection states)
1763 foreach (TreeNode node in col) {
1765 string val = states [ClientID + "_cs_" + node.Path];
1766 if (val != "on") node.Checked = false;
1768 if (node.HasChildData)
1769 UnsetCheckStates (node.ChildNodes, states);
1773 void SetCheckStates (NameValueCollection states)
1775 string keyPrefix = ClientID + "_cs_";
1776 foreach (string key in states) {
1777 if (key.StartsWith (keyPrefix)) {
1778 string id = key.Substring (keyPrefix.Length);
1779 TreeNode node = FindNodeByPos (id);
1781 node.Checked = (Context.Request.Form [key] == "on");
1786 void UnsetExpandStates (TreeNodeCollection col, string[] states)
1788 foreach (TreeNode node in col) {
1789 if (node.Expanded.HasValue && node.Expanded.Value) {
1790 bool expand = (Array.IndexOf (states, node.Path) != -1);
1791 if (!expand) node.Expanded = false;
1793 if (node.HasChildData)
1794 UnsetExpandStates (node.ChildNodes, states);
1798 void SetExpandStates (string[] states)
1800 foreach (string id in states) {
1801 if (id == null || id == "") continue;
1802 TreeNode node = FindNodeByPos (id);
1804 node.Expanded = true;
1808 string GetExpandStates ()
1810 StringBuilder sb = new StringBuilder ("|");
1812 foreach (TreeNode node in Nodes)
1813 GetExpandStates (sb, node);
1815 return sb.ToString ();
1818 void GetExpandStates (StringBuilder sb, TreeNode node)
1820 if (node.Expanded.HasValue && node.Expanded.Value) {
1821 sb.Append (node.Path);
1824 if (node.HasChildData) {
1825 foreach (TreeNode child in node.ChildNodes)
1826 GetExpandStates (sb, child);