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 (null, null, null, "warning", "warning", "warning");
116 imageStyles [TreeViewImageSet.Inbox] = new ImageStyle (null, null, null, "inbox", "inbox", "inbox");
117 imageStyles [TreeViewImageSet.Msdn] = new ImageStyle ("box_plus", "box_minus", "box_noexpand", null, null, null);
118 imageStyles [TreeViewImageSet.Simple] = new ImageStyle (null, null, "box_full", null, null, null);
119 imageStyles [TreeViewImageSet.Simple2] = new ImageStyle (null, null, "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", "folder", "file", "computer");
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, false);
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;
765 OnSelectedNodeChanged (new TreeNodeEventArgs (selectedNode));
768 internal void NotifyCheckChanged (TreeNode node)
770 OnTreeNodeCheckChanged (new TreeNodeEventArgs (node));
773 internal void NotifyExpandedChanged (TreeNode node)
775 if (node.Expanded.HasValue && node.Expanded.Value)
776 OnTreeNodeExpanded (new TreeNodeEventArgs (node));
777 else if (node.Expanded.HasValue && node.IsParentNode)
778 OnTreeNodeCollapsed (new TreeNodeEventArgs (node));
781 internal void NotifyPopulateRequired (TreeNode node)
783 OnTreeNodePopulate (new TreeNodeEventArgs (node));
786 protected override void TrackViewState()
790 base.TrackViewState();
791 if (hoverNodeStyle != null) {
792 hoverNodeStyle.TrackViewState();
794 if (leafNodeStyle != null) {
795 leafNodeStyle.TrackViewState();
797 if (levelStyles != null && levelStyles.Count > 0) {
798 ((IStateManager)levelStyles).TrackViewState();
800 if (nodeStyle != null) {
801 nodeStyle.TrackViewState();
803 if (parentNodeStyle != null) {
804 parentNodeStyle.TrackViewState();
806 if (rootNodeStyle != null) {
807 rootNodeStyle.TrackViewState();
809 if (selectedNodeStyle != null) {
810 selectedNodeStyle.TrackViewState();
812 if (dataBindings != null) {
813 ((IStateManager)dataBindings).TrackViewState ();
816 ((IStateManager)nodes).TrackViewState();;
820 protected override object SaveViewState()
822 object[] states = new object [10];
823 states[0] = base.SaveViewState();
824 states[1] = (hoverNodeStyle == null ? null : hoverNodeStyle.SaveViewState());
825 states[2] = (leafNodeStyle == null ? null : leafNodeStyle.SaveViewState());
826 states[3] = (levelStyles == null ? null : ((IStateManager)levelStyles).SaveViewState());
827 states[4] = (nodeStyle == null ? null : nodeStyle.SaveViewState());
828 states[5] = (parentNodeStyle == null ? null : parentNodeStyle.SaveViewState());
829 states[6] = (rootNodeStyle == null ? null : rootNodeStyle.SaveViewState());
830 states[7] = (selectedNodeStyle == null ? null : selectedNodeStyle.SaveViewState());
831 states[8] = (dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState());
832 states[9] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
834 for (int i = states.Length - 1; i >= 0; i--) {
835 if (states [i] != null)
842 protected override void LoadViewState (object savedState)
844 if (savedState == null)
847 object [] states = (object []) savedState;
848 base.LoadViewState (states[0]);
850 if (states[1] != null)
851 HoverNodeStyle.LoadViewState (states[1]);
852 if (states[2] != null)
853 LeafNodeStyle.LoadViewState(states[2]);
854 if (states[3] != null)
855 ((IStateManager)LevelStyles).LoadViewState(states[3]);
856 if (states[4] != null)
857 NodeStyle.LoadViewState(states[4]);
858 if (states[5] != null)
859 ParentNodeStyle.LoadViewState(states[5]);
860 if (states[6] != null)
861 RootNodeStyle.LoadViewState(states[6]);
862 if (states[7] != null)
863 SelectedNodeStyle.LoadViewState(states[7]);
864 if (states[8] != null)
865 ((IStateManager)DataBindings).LoadViewState(states[8]);
866 if (states[9] != null)
867 ((IStateManager)Nodes).LoadViewState(states[9]);
870 protected virtual void RaisePostBackEvent (string eventArgument)
872 string[] args = eventArgument.Split ('|');
873 TreeNode node = FindNodeByPos (args[1]);
874 if (node == null) return;
876 if (args [0] == "sel")
877 HandleSelectEvent (node);
878 else if (args [0] == "ec")
879 HandleExpandCollapseEvent (node);
882 void HandleSelectEvent (TreeNode node)
884 switch (node.SelectAction) {
885 case TreeNodeSelectAction.Select:
888 case TreeNodeSelectAction.Expand:
891 case TreeNodeSelectAction.SelectExpand:
898 void HandleExpandCollapseEvent (TreeNode node)
900 node.ToggleExpandState ();
903 protected virtual void RaisePostDataChangedEvent ()
907 string callbackResult;
908 protected virtual void RaiseCallbackEvent (string eventArgs)
910 RequiresDataBinding = true;
913 TreeNode node = FindNodeByPos (eventArgs);
914 ArrayList levelLines = new ArrayList ();
917 int childCount = nd.Parent != null ? nd.Parent.ChildNodes.Count : Nodes.Count;
918 levelLines.Insert (0, (nd.Index < childCount - 1) ? this : null);
922 StringWriter sw = new StringWriter ();
923 HtmlTextWriter writer = new HtmlTextWriter (sw);
924 EnsureStylesPrepared ();
926 node.Expanded = true;
927 int num = node.ChildNodes.Count;
928 for (int n=0; n<num; n++)
929 RenderNode (writer, node.ChildNodes [n], node.Depth + 1, levelLines, true, n<num-1);
931 string res = sw.ToString ();
932 callbackResult = res != "" ? res : "*";
935 protected virtual string GetCallbackResult ()
937 return callbackResult;
940 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
942 RaisePostBackEvent (eventArgument);
945 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
947 return LoadPostData (postDataKey, postCollection);
950 void IPostBackDataHandler.RaisePostDataChangedEvent ()
952 RaisePostDataChangedEvent ();
955 void ICallbackEventHandler.RaiseCallbackEvent (string eventArgs)
957 RaiseCallbackEvent (eventArgs);
960 string ICallbackEventHandler.GetCallbackResult ()
962 return GetCallbackResult ();
965 protected override ControlCollection CreateControlCollection ()
967 return new EmptyControlCollection (this);
970 protected internal override void PerformDataBinding ()
972 base.PerformDataBinding ();
973 InitializeDataBindings ();
974 HierarchicalDataSourceView data = GetData ("");
978 IHierarchicalEnumerable e = data.Select ();
979 FillBoundChildrenRecursive (e, Nodes);
982 private void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, TreeNodeCollection nodeCollection)
984 if (hEnumerable == null)
986 foreach (object obj in hEnumerable) {
987 IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
988 TreeNode child = new TreeNode ();
989 nodeCollection.Add (child);
991 OnTreeNodeDataBound (new TreeNodeEventArgs (child));
993 if (MaxDataBindDepth >= 0 && child.Depth == MaxDataBindDepth)
996 if (hdata == null || !hdata.HasChildren)
999 IHierarchicalEnumerable e = hdata.GetChildren ();
1000 FillBoundChildrenRecursive (e, child.ChildNodes);
1004 protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection)
1008 if (EnableClientScript && PopulateNodesFromClient) {
1009 string states = postCollection [ClientID + "_PopulatedStates"];
1010 if (states != null) {
1011 foreach (string id in states.Split ('|')) {
1012 if (String.IsNullOrEmpty(id))
1014 TreeNode node = FindNodeByPos (id);
1015 if (node != null && node.PopulateOnDemand && !node.Populated)
1022 UnsetCheckStates (Nodes, postCollection);
1023 SetCheckStates (postCollection);
1025 if (EnableClientScript) {
1026 string states = postCollection [ClientID + "_ExpandStates"];
1027 if (states != null) {
1028 string[] ids = states.Split ('|');
1029 UnsetExpandStates (Nodes, ids);
1030 SetExpandStates (ids);
1033 UnsetExpandStates (Nodes, new string[0]);
1039 protected internal override void OnPreRender (EventArgs e)
1041 base.OnPreRender (e);
1045 Page.RegisterRequiresPostBack (this);
1047 if (EnableClientScript && !Page.ClientScript.IsClientScriptIncludeRegistered (typeof(TreeView), "TreeView.js")) {
1048 string url = Page.ClientScript.GetWebResourceUrl (typeof(TreeView), "TreeView.js");
1049 Page.ClientScript.RegisterClientScriptInclude (typeof(TreeView), "TreeView.js", url);
1053 string ctree = ClientID + "_data";
1054 string script = string.Format ("var {0} = new Object ();\n", ctree);
1055 script += string.Format ("{0}.treeId = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (ClientID));
1056 script += string.Format ("{0}.uid = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (UniqueID));
1057 script += string.Format ("{0}.showImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (ShowExpandCollapse));
1059 if (ShowExpandCollapse) {
1060 ImageStyle imageStyle = GetImageStyle ();
1061 script += string.Format ("{0}.expandImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("plus", imageStyle)));
1062 script += string.Format ("{0}.collapseImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("minus", imageStyle)));
1063 if (PopulateNodesFromClient)
1064 script += string.Format ("{0}.noExpandImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("noexpand", imageStyle)));
1068 script += string.Format ("{0}.form = {1};\n", ctree, Page.theForm);
1069 script += string.Format (
1070 @"{0}.PopulateNode = function(nodeId) {{
1071 " + Page.WebFormScriptReference + @".__theFormPostData = """";
1072 " + Page.WebFormScriptReference + @".__theFormPostCollection = new Array();
1073 " + Page.WebFormScriptReference + @".WebForm_InitCallback();
1076 ", ctree, Page.ClientScript.GetCallbackEventReference ("this.uid", "nodeId", "TreeView_PopulateCallback", "this.treeId + \" \" + nodeId", "TreeView_PopulateCallback", false));
1077 script += string.Format ("{0}.populateFromClient = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (PopulateNodesFromClient));
1078 script += string.Format ("{0}.expandAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (true, null)));
1079 script += string.Format ("{0}.collapseAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (false, null)));
1081 if (!Page.IsPostBack) {
1082 SetNodesExpandedToDepthRecursive (Nodes);
1085 if (EnableClientScript) {
1086 Page.ClientScript.RegisterHiddenField (ClientID + "_ExpandStates", GetExpandStates ());
1088 // Make sure the basic script infrastructure is rendered
1089 Page.ClientScript.RegisterWebFormClientScript ();
1092 if (EnableClientScript && PopulateNodesFromClient) {
1093 Page.ClientScript.RegisterHiddenField (ClientID + "_PopulatedStates", "|");
1096 EnsureStylesPrepared ();
1098 if (hoverNodeStyle != null) {
1099 if (Page.Header == null)
1100 throw new InvalidOperationException ("Using TreeView.HoverNodeStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
1101 RegisterStyle (HoverNodeStyle, HoverNodeLinkStyle);
1102 script += string.Format ("{0}.hoverClass = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (HoverNodeStyle.RegisteredCssClass));
1103 script += string.Format ("{0}.hoverLinkClass = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (HoverNodeLinkStyle.RegisteredCssClass));
1106 Page.ClientScript.RegisterStartupScript (typeof(TreeView), this.UniqueID, script, true);
1110 void EnsureStylesPrepared () {
1113 stylesPrepared = true;
1117 private void PrepareStyles () {
1118 // The order in which styles are defined matters when more than one class
1119 // is assigned to an element
1120 ControlLinkStyle.CopyTextStylesFrom (ControlStyle);
1121 RegisterStyle (ControlLinkStyle);
1123 if (nodeStyle != null)
1124 RegisterStyle (NodeStyle, NodeLinkStyle);
1126 if (rootNodeStyle != null)
1127 RegisterStyle (RootNodeStyle, RootNodeLinkStyle);
1129 if (parentNodeStyle != null)
1130 RegisterStyle (ParentNodeStyle, ParentNodeLinkStyle);
1132 if (leafNodeStyle != null)
1133 RegisterStyle (LeafNodeStyle, LeafNodeLinkStyle);
1136 if (levelStyles != null && levelStyles.Count > 0) {
1137 levelLinkStyles = new List<Style> (levelStyles.Count);
1138 foreach (Style style in levelStyles) {
1139 Style linkStyle = new Style ();
1140 levelLinkStyles.Add (linkStyle);
1141 RegisterStyle (style, linkStyle);
1145 if (selectedNodeStyle != null)
1146 RegisterStyle (SelectedNodeStyle, SelectedNodeLinkStyle);
1149 void SetNodesExpandedToDepthRecursive (TreeNodeCollection nodes) {
1150 foreach (TreeNode node in nodes) {
1151 if (!node.Expanded.HasValue) {
1152 if (ExpandDepth < 0 || node.Depth < ExpandDepth)
1153 node.Expanded = true;
1155 SetNodesExpandedToDepthRecursive (node.ChildNodes);
1159 string IncrementStyleClassName () {
1160 registeredStylesCounter++;
1161 return ClientID + "_" + registeredStylesCounter;
1164 void RegisterStyle (Style baseStyle, Style linkStyle) {
1165 linkStyle.CopyTextStylesFrom (baseStyle);
1166 linkStyle.BorderStyle = BorderStyle.None;
1167 baseStyle.Font.Reset ();
1168 RegisterStyle (linkStyle);
1169 RegisterStyle (baseStyle);
1172 void RegisterStyle (Style baseStyle) {
1173 if (Page.Header == null)
1175 string className = IncrementStyleClassName ().Trim ('_');
1176 baseStyle.SetRegisteredCssClass (className);
1177 Page.Header.StyleSheet.CreateStyleRule (baseStyle, this, "." + className);
1180 string GetBindingKey (string dataMember, int depth)
1182 return dataMember + " " + depth;
1185 void InitializeDataBindings () {
1186 if (dataBindings != null && dataBindings.Count > 0) {
1187 bindings = new Hashtable ();
1188 foreach (TreeNodeBinding bin in dataBindings) {
1189 string key = GetBindingKey (bin.DataMember, bin.Depth);
1190 bindings [key] = bin;
1197 internal TreeNodeBinding FindBindingForNode (string type, int depth)
1199 if (bindings == null)
1202 TreeNodeBinding bin = (TreeNodeBinding) bindings [GetBindingKey (type, depth)];
1203 if (bin != null) return bin;
1205 bin = (TreeNodeBinding) bindings [GetBindingKey (type, -1)];
1206 if (bin != null) return bin;
1208 bin = (TreeNodeBinding) bindings [GetBindingKey ("", depth)];
1209 if (bin != null) return bin;
1211 return (TreeNodeBinding) bindings [GetBindingKey ("", -1)];
1214 internal void DecorateNode(TreeNode node)
1219 if (node.ImageUrl != null && node.ImageUrl.Length > 0)
1222 if (node.IsRootNode && rootNodeStyle != null) {
1223 node.ImageUrl = rootNodeStyle.ImageUrl;
1226 if (node.IsParentNode && parentNodeStyle != null) {
1227 node.ImageUrl = parentNodeStyle.ImageUrl;
1230 if (node.IsLeafNode && leafNodeStyle != null)
1231 node.ImageUrl = leafNodeStyle.ImageUrl;
1234 protected internal override void RenderContents (HtmlTextWriter writer)
1236 ArrayList levelLines = new ArrayList ();
1237 int num = Nodes.Count;
1238 for (int n=0; n<num; n++)
1239 RenderNode (writer, Nodes [n], 0, levelLines, n>0, n<num-1);
1242 protected override void AddAttributesToRender(HtmlTextWriter writer)
1244 base.AddAttributesToRender (writer);
1247 public override void RenderBeginTag (HtmlTextWriter writer)
1249 if (SkipLinkText != "") {
1250 writer.AddAttribute (HtmlTextWriterAttribute.Href, "#" + ClientID + "_SkipLink");
1251 writer.RenderBeginTag (HtmlTextWriterTag.A);
1253 Image img = new Image ();
1254 ClientScriptManager csm = new ClientScriptManager (null);
1255 img.ImageUrl = csm.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif");
1256 img.Attributes.Add ("height", "0");
1257 img.Attributes.Add ("width", "0");
1258 img.AlternateText = SkipLinkText;
1259 img.Render (writer);
1261 writer.RenderEndTag ();
1263 base.RenderBeginTag (writer);
1266 public override void RenderEndTag (HtmlTextWriter writer)
1268 base.RenderEndTag (writer);
1270 if (SkipLinkText != "") {
1271 writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID + "_SkipLink");
1272 writer.RenderBeginTag (HtmlTextWriterTag.A);
1273 writer.RenderEndTag ();
1277 void RenderNode (HtmlTextWriter writer, TreeNode node, int level, ArrayList levelLines, bool hasPrevious, bool hasNext)
1282 bool clientExpand = EnableClientScript && Events [TreeNodeCollapsedEvent] == null && Events [TreeNodeExpandedEvent] == null;
1283 ImageStyle imageStyle = GetImageStyle ();
1284 bool renderChildNodes = node.Expanded.HasValue && node.Expanded.Value;
1286 if (clientExpand && !renderChildNodes)
1287 renderChildNodes = (!node.PopulateOnDemand || node.Populated);
1291 if (renderChildNodes)
1292 hasChildNodes = node.ChildNodes.Count > 0;
1294 hasChildNodes = (node.PopulateOnDemand && !node.Populated) || node.ChildNodes.Count > 0;
1296 writer.AddAttribute ("cellpadding", "0", false);
1297 writer.AddAttribute ("cellspacing", "0", false);
1298 writer.AddStyleAttribute ("border-width", "0");
1299 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1301 Unit nodeSpacing = GetNodeSpacing (node);
1303 if (nodeSpacing != Unit.Empty && (node.Depth > 0 || node.Index > 0))
1304 RenderMenuItemSpacing (writer, nodeSpacing);
1306 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1308 // Vertical lines from previous levels
1310 nodeImage = GetNodeImageUrl ("i", imageStyle);
1311 for (int n=0; n<level; n++) {
1312 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1313 writer.AddStyleAttribute ("width", NodeIndent + "px");
1314 writer.AddStyleAttribute ("height", "1px");
1315 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1316 if (ShowLines && levelLines [n] != null) {
1317 writer.AddAttribute ("src", nodeImage);
1318 writer.AddAttribute (HtmlTextWriterAttribute.Alt, "", false);
1319 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1320 writer.RenderEndTag ();
1322 writer.RenderEndTag ();
1323 writer.RenderEndTag (); // TD
1326 // Node image + line
1328 if (ShowExpandCollapse || ShowLines) {
1329 bool buttonImage = false;
1330 string tooltip = "";
1334 if (hasPrevious && hasNext) shape = "t";
1335 else if (hasPrevious && !hasNext) shape = "l";
1336 else if (!hasPrevious && hasNext) shape = "r";
1337 else shape = "dash";
1340 if (ShowExpandCollapse) {
1341 if (hasChildNodes) {
1343 if (node.Expanded.HasValue && node.Expanded.Value) shape += "minus";
1344 else shape += "plus";
1345 tooltip = GetNodeImageToolTip (!(node.Expanded.HasValue && node.Expanded.Value), node.Text);
1346 } else if (!ShowLines)
1351 nodeImage = GetNodeImageUrl (shape, imageStyle);
1352 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1355 if (!clientExpand || (!PopulateNodesFromClient && node.PopulateOnDemand && !node.Populated))
1356 writer.AddAttribute ("href", GetClientEvent (node, "ec"));
1358 writer.AddAttribute ("href", GetClientExpandEvent(node));
1359 writer.RenderBeginTag (HtmlTextWriterTag.A); // Anchor
1362 writer.AddAttribute ("alt", tooltip);
1364 if (buttonImage && clientExpand)
1365 writer.AddAttribute ("id", GetNodeClientId (node, "img"));
1366 writer.AddAttribute ("src", nodeImage);
1368 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
1369 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1370 writer.RenderEndTag ();
1373 writer.RenderEndTag (); // Anchor
1375 writer.RenderEndTag (); // TD
1381 string imageUrl = node.ImageUrl.Length > 0 ? ResolveClientUrl (node.ImageUrl) : null;
1382 if (String.IsNullOrEmpty (imageUrl) && imageStyle != null) {
1383 if (imageStyle.RootIcon != null && node.IsRootNode)
1384 imageUrl = GetNodeIconUrl (imageStyle.RootIcon);
1385 else if (imageStyle.ParentIcon != null && node.IsParentNode)
1386 imageUrl = GetNodeIconUrl (imageStyle.ParentIcon);
1387 else if (imageStyle.LeafIcon != null && node.IsLeafNode)
1388 imageUrl = GetNodeIconUrl (imageStyle.LeafIcon);
1391 if (level < LevelStyles.Count && LevelStyles [level].ImageUrl != null)
1392 imageUrl = ResolveClientUrl (LevelStyles [level].ImageUrl);
1394 if (!String.IsNullOrEmpty (imageUrl)) {
1395 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1396 BeginNodeTag (writer, node, clientExpand);
1397 writer.AddAttribute ("src", imageUrl);
1398 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
1399 writer.AddAttribute ("alt", node.ImageToolTip);
1400 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1401 writer.RenderEndTag (); // IMG
1402 writer.RenderEndTag (); // style tag
1403 writer.RenderEndTag (); // TD
1407 writer.AddStyleAttribute ("white-space", "nowrap");
1408 AddNodeStyle (writer, node, level);
1409 if (EnableClientScript) {
1410 writer.AddAttribute ("onmouseout", "TreeView_UnhoverNode(this)", false);
1411 writer.AddAttribute ("onmouseover", "TreeView_HoverNode('" + ClientID + "', this)");
1413 writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
1417 if (node.ShowCheckBoxInternal) {
1418 writer.AddAttribute ("name", ClientID + "_cs_" + node.Path);
1419 writer.AddAttribute ("type", "checkbox", false);
1420 writer.AddAttribute ("title", node.Text);
1421 if (node.Checked) writer.AddAttribute ("checked", "checked", false);
1422 writer.RenderBeginTag (HtmlTextWriterTag.Input); // INPUT
1423 writer.RenderEndTag (); // INPUT
1428 node.BeginRenderText (writer);
1431 writer.AddAttribute ("id", GetNodeClientId (node, "txt"));
1432 AddNodeLinkStyle (writer, node, level);
1433 BeginNodeTag (writer, node, clientExpand);
1434 writer.Write (node.Text);
1435 writer.RenderEndTag (); // style tag
1437 node.EndRenderText (writer);
1439 writer.RenderEndTag (); // TD
1441 writer.RenderEndTag (); // TR
1443 if (nodeSpacing != Unit.Empty)
1444 RenderMenuItemSpacing (writer, nodeSpacing);
1446 writer.RenderEndTag (); // TABLE
1450 if (hasChildNodes) {
1451 if (level >= levelLines.Count) {
1453 levelLines.Add (this);
1455 levelLines.Add (null);
1458 levelLines [level] = this;
1460 levelLines [level] = null;
1464 if (!(node.Expanded.HasValue && node.Expanded.Value))
1465 writer.AddStyleAttribute ("display", "none");
1467 writer.AddStyleAttribute ("display", "block");
1468 writer.AddAttribute ("id", GetNodeClientId (node, null));
1469 writer.RenderBeginTag (HtmlTextWriterTag.Span);
1471 if (renderChildNodes) {
1472 AddChildrenPadding (writer, node);
1473 int num = node.ChildNodes.Count;
1474 for (int n=0; n<num; n++)
1475 RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
1477 AddChildrenPadding (writer, node);
1479 writer.RenderEndTag (); // SPAN
1480 } else if (renderChildNodes) {
1481 AddChildrenPadding (writer, node);
1482 int num = node.ChildNodes.Count;
1483 for (int n=0; n<num; n++)
1484 RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
1486 AddChildrenPadding (writer, node);
1491 private void AddChildrenPadding (HtmlTextWriter writer, TreeNode node)
1493 int level = node.Depth;
1494 Unit cnp = Unit.Empty;
1496 if (levelStyles != null && level < levelStyles.Count)
1497 cnp = levelStyles [level].ChildNodesPadding;
1498 if (cnp.IsEmpty && nodeStyle != null)
1499 cnp = nodeStyle.ChildNodesPadding;
1502 if (cnp.IsEmpty || (value = cnp.Value) == 0 || cnp.Type != UnitType.Pixel)
1505 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1506 writer.AddAttribute ("height", ((int) value).ToString (), false);
1507 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1508 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1509 writer.RenderEndTag (); // td
1510 writer.RenderEndTag (); // tr
1511 writer.RenderEndTag (); // table
1514 private void RenderMenuItemSpacing (HtmlTextWriter writer, Unit itemSpacing) {
1515 writer.AddStyleAttribute ("height", itemSpacing.ToString ());
1516 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1517 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1518 writer.RenderEndTag ();
1519 writer.RenderEndTag ();
1522 private Unit GetNodeSpacing (TreeNode node) {
1523 if (node.Selected && selectedNodeStyle != null && selectedNodeStyle.NodeSpacing != Unit.Empty) {
1524 return selectedNodeStyle.NodeSpacing;
1527 if (levelStyles != null && node.Depth < levelStyles.Count && levelStyles [node.Depth].NodeSpacing != Unit.Empty) {
1528 return levelStyles [node.Depth].NodeSpacing;
1531 if (node.IsLeafNode) {
1532 if (leafNodeStyle != null && leafNodeStyle.NodeSpacing != Unit.Empty)
1533 return leafNodeStyle.NodeSpacing;
1535 else if (node.IsRootNode) {
1536 if (rootNodeStyle != null && rootNodeStyle.NodeSpacing != Unit.Empty)
1537 return rootNodeStyle.NodeSpacing;
1539 else if (node.IsParentNode) {
1540 if (parentNodeStyle != null && parentNodeStyle.NodeSpacing != Unit.Empty)
1541 return parentNodeStyle.NodeSpacing;
1544 if (nodeStyle != null)
1545 return nodeStyle.NodeSpacing;
1550 void AddNodeStyle (HtmlTextWriter writer, TreeNode node, int level)
1552 TreeNodeStyle style = new TreeNodeStyle ();
1553 if (Page.Header != null) {
1554 // styles are registered
1555 if (nodeStyle != null) {
1556 style.AddCssClass (nodeStyle.CssClass);
1557 style.AddCssClass (nodeStyle.RegisteredCssClass);
1559 if (node.IsLeafNode) {
1560 if (leafNodeStyle != null) {
1561 style.AddCssClass (leafNodeStyle.CssClass);
1562 style.AddCssClass (leafNodeStyle.RegisteredCssClass);
1565 else if (node.IsRootNode) {
1566 if (rootNodeStyle != null) {
1567 style.AddCssClass (rootNodeStyle.CssClass);
1568 style.AddCssClass (rootNodeStyle.RegisteredCssClass);
1571 else if (node.IsParentNode) {
1572 if (parentNodeStyle != null) {
1573 style.AddCssClass (parentNodeStyle.CssClass);
1574 style.AddCssClass (parentNodeStyle.RegisteredCssClass);
1577 if (levelStyles != null && levelStyles.Count > level) {
1578 style.AddCssClass (levelStyles [level].CssClass);
1579 style.AddCssClass (levelStyles [level].RegisteredCssClass);
1581 if (node == SelectedNode && selectedNodeStyle != null) {
1582 style.AddCssClass (selectedNodeStyle.CssClass);
1583 style.AddCssClass (selectedNodeStyle.RegisteredCssClass);
1587 // styles are not registered
1588 if (nodeStyle != null) {
1589 style.CopyFrom (nodeStyle);
1591 if (node.IsLeafNode) {
1592 if (leafNodeStyle != null) {
1593 style.CopyFrom (leafNodeStyle);
1596 else if (node.IsRootNode) {
1597 if (rootNodeStyle != null) {
1598 style.CopyFrom (rootNodeStyle);
1601 else if (node.IsParentNode) {
1602 if (parentNodeStyle != null) {
1603 style.CopyFrom (parentNodeStyle);
1606 if (levelStyles != null && levelStyles.Count > level) {
1607 style.CopyFrom (levelStyles [level]);
1609 if (node == SelectedNode && selectedNodeStyle != null) {
1610 style.CopyFrom (selectedNodeStyle);
1613 style.AddAttributesToRender (writer);
1616 void AddNodeLinkStyle (HtmlTextWriter writer, TreeNode node, int level) {
1617 Style style = new Style ();
1618 if (Page.Header != null) {
1619 // styles are registered
1620 style.AddCssClass (ControlLinkStyle.RegisteredCssClass);
1622 if (nodeStyle != null) {
1623 style.AddCssClass (nodeLinkStyle.CssClass);
1624 style.AddCssClass (nodeLinkStyle.RegisteredCssClass);
1626 if (node.IsLeafNode) {
1627 if (leafNodeStyle != null) {
1628 style.AddCssClass (leafNodeLinkStyle.CssClass);
1629 style.AddCssClass (leafNodeLinkStyle.RegisteredCssClass);
1632 else if (node.IsRootNode) {
1633 if (rootNodeStyle != null) {
1634 style.AddCssClass (rootNodeLinkStyle.CssClass);
1635 style.AddCssClass (rootNodeLinkStyle.RegisteredCssClass);
1638 else if (node.IsParentNode) {
1639 if (parentNodeStyle != null) {
1640 style.AddCssClass (parentNodeLinkStyle.CssClass);
1641 style.AddCssClass (parentNodeLinkStyle.RegisteredCssClass);
1644 if (levelStyles != null && levelStyles.Count > level) {
1645 style.AddCssClass (levelLinkStyles [level].CssClass);
1646 style.AddCssClass (levelLinkStyles [level].RegisteredCssClass);
1648 if (node == SelectedNode && selectedNodeStyle != null) {
1649 style.AddCssClass (selectedNodeLinkStyle.CssClass);
1650 style.AddCssClass (selectedNodeLinkStyle.RegisteredCssClass);
1654 // styles are not registered
1655 style.CopyFrom (ControlLinkStyle);
1656 if (nodeStyle != null) {
1657 style.CopyFrom (nodeLinkStyle);
1659 if (node.IsLeafNode) {
1660 if (node.IsLeafNode && leafNodeStyle != null) {
1661 style.CopyFrom (leafNodeLinkStyle);
1664 else if (node.IsRootNode) {
1665 if (node.IsRootNode && rootNodeStyle != null) {
1666 style.CopyFrom (rootNodeLinkStyle);
1669 else if (node.IsParentNode) {
1670 if (node.IsParentNode && parentNodeStyle != null) {
1671 style.CopyFrom (parentNodeLinkStyle);
1674 if (levelStyles != null && levelStyles.Count > level) {
1675 style.CopyFrom (levelLinkStyles [level]);
1677 if (node == SelectedNode && selectedNodeStyle != null) {
1678 style.CopyFrom (selectedNodeLinkStyle);
1680 style.AlwaysRenderTextDecoration = true;
1682 style.AddAttributesToRender (writer);
1685 void BeginNodeTag (HtmlTextWriter writer, TreeNode node, bool clientExpand)
1687 if(node.ToolTip.Length>0)
1688 writer.AddAttribute ("title", node.ToolTip);
1690 if (node.NavigateUrl != "") {
1691 string target = node.Target.Length > 0 ? node.Target : Target;
1693 string navUrl = ResolveClientUrl (node.NavigateUrl, String.Compare (target, "_blank", StringComparison.InvariantCultureIgnoreCase) != 0);
1695 string navUrl = ResolveClientUrl (node.NavigateUrl);
1697 writer.AddAttribute ("href", navUrl);
1698 if (target.Length > 0)
1699 writer.AddAttribute ("target", target);
1700 writer.RenderBeginTag (HtmlTextWriterTag.A);
1702 else if (node.SelectAction != TreeNodeSelectAction.None) {
1703 if (node.SelectAction == TreeNodeSelectAction.Expand && clientExpand)
1704 writer.AddAttribute ("href", GetClientExpandEvent (node));
1706 writer.AddAttribute ("href", GetClientEvent (node, "sel"));
1707 writer.RenderBeginTag (HtmlTextWriterTag.A);
1710 writer.RenderBeginTag (HtmlTextWriterTag.Span);
1713 string GetNodeImageToolTip (bool expand, string txt) {
1715 if (ExpandImageToolTip != "")
1716 return String.Format (ExpandImageToolTip, txt);
1717 else if (txt != null)
1718 return "Expand " + txt;
1720 return "Expand {0}";
1722 if (CollapseImageToolTip != "")
1723 return String.Format (CollapseImageToolTip, txt);
1724 else if (txt != null)
1725 return "Collapse " + txt;
1727 return "Collapse {0}";
1731 string GetNodeClientId (TreeNode node, string sufix)
1733 return ClientID + "_" + node.Path + (sufix != null ? "_" + sufix : "");
1736 string GetNodeImageUrl (string shape, ImageStyle imageStyle)
1739 if (!String.IsNullOrEmpty (LineImagesFolder))
1740 return ResolveClientUrl (LineImagesFolder + "/" + shape + ".gif");
1742 if (imageStyle != null) {
1743 if (shape == "plus") {
1744 if (!String.IsNullOrEmpty (imageStyle.Expand))
1745 return GetNodeIconUrl (imageStyle.Expand);
1747 else if (shape == "minus") {
1748 if (!String.IsNullOrEmpty (imageStyle.Collapse))
1749 return GetNodeIconUrl (imageStyle.Collapse);
1751 else if (shape == "noexpand") {
1752 if (!String.IsNullOrEmpty (imageStyle.NoExpand))
1753 return GetNodeIconUrl (imageStyle.NoExpand);
1757 if (shape == "plus") {
1758 if (!String.IsNullOrEmpty (ExpandImageUrl))
1759 return ResolveClientUrl (ExpandImageUrl);
1761 else if (shape == "minus") {
1762 if (!String.IsNullOrEmpty (CollapseImageUrl))
1763 return ResolveClientUrl (CollapseImageUrl);
1765 else if (shape == "noexpand") {
1766 if (!String.IsNullOrEmpty (NoExpandImageUrl))
1767 return ResolveClientUrl (NoExpandImageUrl);
1770 if (!String.IsNullOrEmpty (LineImagesFolder))
1771 return ResolveClientUrl (LineImagesFolder + "/" + shape + ".gif");
1773 return Page.ClientScript.GetWebResourceUrl (typeof (TreeView), "TreeView_" + shape + ".gif");
1776 string GetNodeIconUrl (string icon)
1778 return Page.ClientScript.GetWebResourceUrl (typeof (TreeView), icon + ".gif");
1781 string GetClientEvent (TreeNode node, string ev)
1783 return Page.ClientScript.GetPostBackClientHyperlink (this, ev + "|" + node.Path, true);
1786 string GetClientExpandEvent (TreeNode node)
1788 return "javascript:TreeView_ToggleExpand ('" + ClientID + "', '" + node.Path + "')";
1791 TreeNode FindNodeByPos (string path)
1793 string[] indexes = path.Split ('_');
1794 TreeNode node = null;
1796 foreach (string index in indexes) {
1797 int i = int.Parse (index);
1799 if (i >= Nodes.Count) return null;
1802 if (i >= node.ChildNodes.Count) return null;
1803 node = node.ChildNodes [i];
1809 void UnsetCheckStates (TreeNodeCollection col, NameValueCollection states)
1811 foreach (TreeNode node in col) {
1812 if (node.ShowCheckBoxInternal && node.Checked) {
1813 if (states == null || states [ClientID + "_cs_" + node.Path] == null)
1814 node.Checked = false;
1816 if (node.HasChildData)
1817 UnsetCheckStates (node.ChildNodes, states);
1821 void SetCheckStates (NameValueCollection states)
1826 string keyPrefix = ClientID + "_cs_";
1827 foreach (string key in states) {
1828 if (key.StartsWith (keyPrefix, StringComparison.Ordinal)) {
1829 string id = key.Substring (keyPrefix.Length);
1830 TreeNode node = FindNodeByPos (id);
1831 if (node != null && !node.Checked)
1832 node.Checked = true;
1837 void UnsetExpandStates (TreeNodeCollection col, string[] states)
1839 foreach (TreeNode node in col) {
1840 if (node.Expanded.HasValue && node.Expanded.Value) {
1841 bool expand = (Array.IndexOf (states, node.Path) != -1);
1842 if (!expand) node.Expanded = false;
1844 if (node.HasChildData)
1845 UnsetExpandStates (node.ChildNodes, states);
1849 void SetExpandStates (string[] states)
1851 foreach (string id in states) {
1852 if (id == null || id == "") continue;
1853 TreeNode node = FindNodeByPos (id);
1855 node.Expanded = true;
1859 string GetExpandStates ()
1861 StringBuilder sb = new StringBuilder ("|");
1863 foreach (TreeNode node in Nodes)
1864 GetExpandStates (sb, node);
1866 return sb.ToString ();
1869 void GetExpandStates (StringBuilder sb, TreeNode node)
1871 if (node.Expanded.HasValue && node.Expanded.Value) {
1872 sb.Append (node.Path);
1875 if (node.HasChildData) {
1876 foreach (TreeNode child in node.ChildNodes)
1877 GetExpandStates (sb, child);