2 // System.Web.UI.WebControls.TreeNode.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)
34 using System.Collections;
36 using System.ComponentModel;
39 namespace System.Web.UI.WebControls
41 [ParseChildrenAttribute (true, "ChildNodes")]
42 public class TreeNode: IStateManager, ICloneable
44 StateBag ViewState = new StateBag ();
45 TreeNodeCollection nodes;
54 IHierarchyData hierarchyData;
57 TreeNodeBinding binding;
58 PropertyDescriptorCollection boundProperties;
60 bool hadChildrenBeforePopulating;
62 internal TreeNode (TreeView tree)
71 public TreeNode (string text)
76 public TreeNode (string text, string value)
82 public TreeNode (string text, string value, string imageUrl)
89 public TreeNode (string text, string value, string imageUrl, string navigateUrl, string target)
94 NavigateUrl = navigateUrl;
98 [MonoTODO ("Not implemented")]
99 protected TreeNode (TreeView owner, bool isRoot)
101 throw new NotImplementedException ();
104 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
108 if (depth != -1) return depth;
110 TreeNode nod = parent;
111 while (nod != null) {
119 void ResetPathData ()
125 foreach (TreeNode node in nodes)
126 node.ResetPathData ();
130 internal TreeView Tree {
135 value.SetSelectedNode (this, false);
139 nodes.SetTree (tree);
141 if (PopulateOnDemand && !Populated && Expanded.HasValue && Expanded.Value)
146 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
147 [DefaultValue (false)]
149 public bool DataBound {
150 get { return ViewState ["DataBound"] == null ? false : (bool) ViewState ["DataBound"]; }
151 private set { ViewState ["DataBound"] = value; }
154 [DefaultValue (null)]
156 public object DataItem {
157 get { return dataItem; }
160 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
163 public string DataPath {
164 get { return ViewState ["DataPath"] == null ? String.Empty : (String) ViewState ["DataPath"]; }
165 private set { ViewState ["DataPath"] = value; }
168 [DefaultValue (false)]
169 public bool Checked {
171 object o = ViewState ["Checked"];
172 if (o != null) return (bool)o;
176 ViewState ["Checked"] = value;
178 tree.NotifyCheckChanged (this);
182 [DefaultValue (null)]
183 [MergableProperty (false)]
185 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
186 public TreeNodeCollection ChildNodes {
189 nodes = new TreeNodeCollection (this);
191 if (IsTrackingViewState)
192 ((IStateManager)nodes).TrackViewState();
198 [DefaultValue (null)]
199 public bool? Expanded {
201 object o = ViewState ["Expanded"];
205 bool? current = (bool?) ViewState ["Expanded"];
206 if (current == value)
208 ViewState ["Expanded"] = value;
210 tree.NotifyExpandedChanged (this);
211 if (PopulateOnDemand && !Populated && value.HasValue && value.Value)
218 public string ImageToolTip {
220 object o = ViewState ["ImageToolTip"];
225 set { ViewState ["ImageToolTip"] = value; }
230 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
231 public string ImageUrl {
233 object o = ViewState ["ImageUrl"];
238 set { ViewState ["ImageUrl"] = value; }
243 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
244 public string NavigateUrl {
246 object o = ViewState ["NavigateUrl"];
251 set { ViewState ["NavigateUrl"] = value; }
254 internal bool HadChildrenBeforePopulating {
255 get { return hadChildrenBeforePopulating; }
260 hadChildrenBeforePopulating = value;
264 [DefaultValue (false)]
265 public bool PopulateOnDemand {
267 object o = ViewState ["PopulateOnDemand"];
273 ViewState ["PopulateOnDemand"] = value;
274 if (value && nodes != null && nodes.Count > 0)
275 HadChildrenBeforePopulating = true;
277 HadChildrenBeforePopulating = false;
281 [DefaultValue (TreeNodeSelectAction.Select)]
282 public TreeNodeSelectAction SelectAction {
284 object o = ViewState ["SelectAction"];
286 return (TreeNodeSelectAction)o;
287 return TreeNodeSelectAction.Select;
289 set { ViewState ["SelectAction"] = value; }
292 [DefaultValue (null)]
293 public bool? ShowCheckBox {
295 object o = ViewState ["ShowCheckBox"];
298 set { ViewState ["ShowCheckBox"] = value; }
301 internal bool ShowCheckBoxInternal {
303 if (ShowCheckBox.HasValue)
304 return ShowCheckBox.Value;
306 return (Tree.ShowCheckBoxes == TreeNodeTypes.All) ||
307 ((Tree.ShowCheckBoxes & TreeNodeTypes.Leaf) > 0 && IsLeafNode) ||
308 ((Tree.ShowCheckBoxes & TreeNodeTypes.Parent) > 0 && IsParentNode && Parent != null) ||
309 ((Tree.ShowCheckBoxes & TreeNodeTypes.Root) > 0 && Parent == null && ChildNodes.Count > 0);
314 public string Target {
316 object o = ViewState ["Target"];
321 set { ViewState ["Target"] = value; }
326 [WebSysDescription ("The display text of the tree node.")]
329 object o = ViewState ["Text"];
331 o = ViewState ["Value"];
336 set { ViewState ["Text"] = value; }
341 public string ToolTip {
343 object o = ViewState ["ToolTip"];
348 set { ViewState ["ToolTip"] = value; }
353 public string Value {
355 object o = ViewState ["Value"];
357 o = ViewState ["Text"];
362 set { ViewState ["Value"] = value; }
365 [DefaultValue (false)]
366 public bool Selected {
367 get { return SelectedFlag; }
369 SelectedFlag = value;
372 if (!value && tree.SelectedNode == this)
373 tree.SetSelectedNode (null, false);
375 tree.SetSelectedNode (this, false);
380 internal virtual bool SelectedFlag {
382 object o = ViewState ["Selected"];
387 set { ViewState ["Selected"] = value; }
390 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
392 public TreeNode Parent {
393 get { return parent; }
396 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
398 public string ValuePath {
400 if (tree == null) return Value;
402 StringBuilder sb = new StringBuilder (Value);
403 TreeNode node = parent;
404 while (node != null) {
405 sb.Insert (0, tree.PathSeparator);
406 sb.Insert (0, node.Value);
409 return sb.ToString ();
414 get { return index; }
415 set { index = value; ResetPathData (); }
418 internal void SetParent (TreeNode node)
424 internal string Path {
428 StringBuilder sb = new StringBuilder (index.ToString());
429 TreeNode node = parent;
430 while (node != null) {
432 sb.Insert (0, node.Index.ToString ());
435 path = sb.ToString ();
440 internal bool Populated {
442 object o = ViewState ["Populated"];
447 set { ViewState ["Populated"] = value; }
450 internal bool HasChildData {
451 get { return nodes != null; }
454 internal void Populate ()
460 tree.NotifyPopulateRequired (this);
465 public void Collapse ()
470 public void CollapseAll ()
472 SetExpandedRec (false, -1);
475 public void Expand ()
480 internal void Expand (int depth)
482 SetExpandedRec (true, depth);
485 public void ExpandAll ()
487 SetExpandedRec (true, -1);
490 void SetExpandedRec (bool expanded, int depth)
496 foreach (TreeNode nod in ChildNodes)
497 nod.SetExpandedRec (expanded, depth - 1);
500 public void Select ()
505 public void ToggleExpandState ()
507 #if TARGET_JVM //No support for Nullable<bool>.GetValueOrDefault() yet
508 bool? value = Expanded;
509 Expanded = value.HasValue ? !value.Value : true;
511 Expanded = !Expanded.GetValueOrDefault(false);
515 void IStateManager.LoadViewState (object savedState)
517 LoadViewState (savedState);
520 protected virtual void LoadViewState (object savedState)
522 if (savedState == null)
525 object[] states = (object[]) savedState;
526 ViewState.LoadViewState (states [0]);
528 if (tree != null && SelectedFlag)
529 tree.SetSelectedNode (this, true);
531 if (!PopulateOnDemand || Populated)
532 ((IStateManager)ChildNodes).LoadViewState (states [1]);
535 object IStateManager.SaveViewState ()
537 return SaveViewState ();
540 protected virtual object SaveViewState ()
542 object[] states = new object[2];
543 states[0] = ViewState.SaveViewState();
544 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
546 for (int i = 0; i < states.Length; i++) {
547 if (states [i] != null)
553 void IStateManager.TrackViewState ()
558 protected void TrackViewState ()
562 ViewState.TrackViewState();
565 ((IStateManager)nodes).TrackViewState ();
568 bool IStateManager.IsTrackingViewState {
569 get { return IsTrackingViewState; }
572 protected bool IsTrackingViewState {
573 get { return marked; }
576 internal void SetDirty ()
578 ViewState.SetDirty (true);
583 public virtual object Clone ()
585 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
586 foreach (DictionaryEntry e in ViewState)
587 nod.ViewState [(string)e.Key] = ((StateItem)e.Value).Value;
589 foreach (TreeNode c in ChildNodes)
590 nod.ChildNodes.Add ((TreeNode)c.Clone ());
595 object ICloneable.Clone ()
600 internal void Bind (IHierarchyData hierarchyData)
602 this.hierarchyData = hierarchyData;
604 DataPath = hierarchyData.Path;
605 dataItem = hierarchyData.Item;
607 TreeNodeBinding bin = GetBinding ();
610 // Bind ImageToolTip property
612 if (bin.ImageToolTipField.Length > 0) {
613 ImageToolTip = Convert.ToString (GetBoundPropertyValue (bin.ImageToolTipField));
614 if (ImageToolTip.Length == 0)
615 ImageToolTip = bin.ImageToolTip;
616 } else if (bin.ImageToolTip.Length > 0)
617 ImageToolTip = bin.ImageToolTip;
619 // Bind ImageUrl property
621 if (bin.ImageUrlField.Length > 0) {
622 ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
623 if (ImageUrl.Length == 0)
624 ImageUrl = bin.ImageUrl;
625 } else if (bin.ImageUrl.Length > 0)
626 ImageUrl = bin.ImageUrl;
628 // Bind NavigateUrl property
630 if (bin.NavigateUrlField.Length > 0) {
631 NavigateUrl = Convert.ToString (GetBoundPropertyValue (bin.NavigateUrlField));
632 if (NavigateUrl.Length == 0)
633 NavigateUrl = bin.NavigateUrl;
634 } else if (bin.NavigateUrl.Length > 0)
635 NavigateUrl = bin.NavigateUrl;
637 // Bind PopulateOnDemand property
639 if (bin.HasPropertyValue ("PopulateOnDemand"))
640 PopulateOnDemand = bin.PopulateOnDemand;
642 // Bind SelectAction property
644 if (bin.HasPropertyValue ("SelectAction"))
645 SelectAction = bin.SelectAction;
647 // Bind ShowCheckBox property
649 if (bin.HasPropertyValue ("ShowCheckBox"))
650 ShowCheckBox = bin.ShowCheckBox;
652 // Bind Target property
654 if (bin.TargetField.Length > 0) {
655 Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
656 if (Target.Length == 0)
658 } else if (bin.Target.Length > 0)
661 // Bind Text property
663 if (bin.TextField.Length > 0) {
664 text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
665 if (bin.FormatString.Length > 0)
666 text = string.Format (bin.FormatString, text);
668 if (String.IsNullOrEmpty (text)) {
669 if (bin.Text.Length > 0)
671 else if (bin.Value.Length > 0)
674 if (!String.IsNullOrEmpty (text))
677 // Bind ToolTip property
679 if (bin.ToolTipField.Length > 0) {
680 ToolTip = Convert.ToString (GetBoundPropertyValue (bin.ToolTipField));
681 if (ToolTip.Length == 0)
682 ToolTip = bin.ToolTip;
683 } else if (bin.ToolTip.Length > 0)
684 ToolTip = bin.ToolTip;
686 // Bind Value property
688 if (bin.ValueField.Length > 0) {
689 value = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
691 if (String.IsNullOrEmpty (value)) {
692 if (bin.Value.Length > 0)
694 else if (bin.Text.Length > 0)
697 if (!String.IsNullOrEmpty (value))
700 Text = Value = GetDefaultBoundText ();
703 INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
704 if (navigateUIData != null) {
705 SelectAction = TreeNodeSelectAction.None;
706 Text = navigateUIData.ToString ();
707 NavigateUrl = navigateUIData.NavigateUrl;
708 ToolTip = navigateUIData.Description;
712 internal void SetDataItem (object item)
717 internal void SetDataPath (string path)
722 internal void SetDataBound (bool bound)
727 string GetDefaultBoundText ()
729 if (hierarchyData != null)
730 return hierarchyData.ToString ();
731 else if (dataItem != null)
732 return dataItem.ToString ();
737 string GetDataItemType ()
739 if (hierarchyData != null)
740 return hierarchyData.Type;
741 else if (dataItem != null)
742 return dataItem.GetType().ToString ();
747 internal bool IsParentNode {
748 get { return ChildNodes.Count > 0 || (PopulateOnDemand && !Populated); }
751 internal bool IsLeafNode {
752 get { return !IsParentNode; }
755 internal bool IsRootNode {
756 get { return Depth == 0; }
759 TreeNodeBinding GetBinding ()
765 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
770 object GetBoundPropertyValue (string name)
772 if (boundProperties == null) {
773 if (hierarchyData != null)
774 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
776 boundProperties = TypeDescriptor.GetProperties (dataItem);
779 PropertyDescriptor prop = boundProperties.Find (name, true);
781 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
783 if (hierarchyData != null)
784 return prop.GetValue (hierarchyData);
786 return prop.GetValue (dataItem);
789 internal void BeginRenderText (HtmlTextWriter writer)
791 RenderPreText (writer);
794 internal void EndRenderText (HtmlTextWriter writer)
796 RenderPostText (writer);
799 protected virtual void RenderPreText (HtmlTextWriter writer)
803 protected virtual void RenderPostText (HtmlTextWriter writer)