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 internal TreeNode (TreeView tree)
69 public TreeNode (string text)
74 public TreeNode (string text, string value)
80 public TreeNode (string text, string value, string imageUrl)
87 public TreeNode (string text, string value, string imageUrl, string navigateUrl, string target)
92 NavigateUrl = navigateUrl;
96 [MonoTODO ("Not implemented")]
97 protected TreeNode (TreeView owner, bool isRoot)
99 throw new NotImplementedException ();
102 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
106 if (depth != -1) return depth;
108 TreeNode nod = parent;
109 while (nod != null) {
117 void ResetPathData ()
124 internal TreeView Tree {
129 value.SetSelectedNode (this, false);
131 tree.SetSelectedNode (null, false);
135 nodes.SetTree (tree);
137 if (PopulateOnDemand && !Populated && Expanded.HasValue && Expanded.Value)
142 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
143 [DefaultValue (false)]
145 public bool DataBound {
146 get { return ViewState ["DataBound"] == null ? false : (bool) ViewState ["DataBound"]; }
147 private set { ViewState ["DataBound"] = value; }
150 [DefaultValue (null)]
152 public object DataItem {
158 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
161 public string DataPath {
162 get { return ViewState ["DataPath"] == null ? String.Empty : (String) ViewState ["DataPath"]; }
163 private set { ViewState ["DataPath"] = value; }
166 [DefaultValue (false)]
167 public bool Checked {
169 object o = ViewState ["Checked"];
170 if (o != null) return (bool)o;
174 ViewState ["Checked"] = value;
176 tree.NotifyCheckChanged (this);
180 [DefaultValue (null)]
181 [MergableProperty (false)]
183 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
184 public TreeNodeCollection ChildNodes {
187 nodes = new TreeNodeCollection (this);
189 if (IsTrackingViewState)
190 ((IStateManager)nodes).TrackViewState();
196 [DefaultValue (null)]
197 public bool? Expanded {
199 object o = ViewState ["Expanded"];
203 bool? current = (bool?) ViewState ["Expanded"];
204 if (current == value)
206 ViewState ["Expanded"] = value;
208 tree.NotifyExpandedChanged (this);
209 if (PopulateOnDemand && !Populated && value.HasValue && value.Value)
216 public string ImageToolTip {
218 object o = ViewState ["ImageToolTip"];
219 if (o != null) return (string)o;
223 ViewState ["ImageToolTip"] = value;
229 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
230 public string ImageUrl {
232 object o = ViewState ["ImageUrl"];
233 if (o != null) return (string)o;
237 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"];
247 if (o != null) return (string)o;
251 ViewState ["NavigateUrl"] = value;
255 [DefaultValue (false)]
256 public bool PopulateOnDemand {
258 object o = ViewState ["PopulateOnDemand"];
259 if (o != null) return (bool)o;
263 ViewState ["PopulateOnDemand"] = value;
267 [DefaultValue (TreeNodeSelectAction.Select)]
268 public TreeNodeSelectAction SelectAction {
270 object o = ViewState ["SelectAction"];
271 if (o != null) return (TreeNodeSelectAction)o;
272 return TreeNodeSelectAction.Select;
275 ViewState ["SelectAction"] = value;
279 [DefaultValue (null)]
280 public bool? ShowCheckBox {
282 object o = ViewState ["ShowCheckBox"];
286 ViewState ["ShowCheckBox"] = value;
290 internal bool ShowCheckBoxInternal {
292 if (ShowCheckBox.HasValue)
293 return ShowCheckBox.Value;
295 return (Tree.ShowCheckBoxes == TreeNodeTypes.All) ||
296 ((Tree.ShowCheckBoxes & TreeNodeTypes.Leaf) > 0 && IsLeafNode) ||
297 ((Tree.ShowCheckBoxes & TreeNodeTypes.Parent) > 0 && IsParentNode && Parent != null) ||
298 ((Tree.ShowCheckBoxes & TreeNodeTypes.Root) > 0 && Parent == null && ChildNodes.Count > 0);
303 public string Target {
305 object o = ViewState ["Target"];
306 if(o != null) return (string)o;
310 ViewState ["Target"] = value;
316 [WebSysDescription ("The display text of the tree node.")]
319 object o = ViewState ["Text"];
321 o = ViewState ["Value"];
322 if (o != null) return (string)o;
326 ViewState ["Text"] = value;
332 public string ToolTip {
334 object o = ViewState ["ToolTip"];
335 if(o != null) return (string)o;
339 ViewState ["ToolTip"] = value;
345 public string Value {
347 object o = ViewState ["Value"];
349 o = ViewState ["Text"];
350 if(o != null) return (string)o;
354 ViewState ["Value"] = value;
358 [DefaultValue (false)]
359 public bool Selected {
364 SelectedFlag = value;
367 if (!value && tree.SelectedNode == this)
368 tree.SetSelectedNode (null, false);
370 tree.SetSelectedNode (this, false);
375 internal virtual bool SelectedFlag {
377 object o = ViewState ["Selected"];
378 if(o != null) return (bool)o;
382 ViewState ["Selected"] = value;
386 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
388 public TreeNode Parent {
389 get { return parent; }
392 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
394 public string ValuePath {
396 if (tree == null) return Value;
398 StringBuilder sb = new StringBuilder (Value);
399 TreeNode node = parent;
400 while (node != null) {
401 sb.Insert (0, tree.PathSeparator);
402 sb.Insert (0, node.Value);
405 return sb.ToString ();
410 get { return index; }
411 set { index = value; ResetPathData (); }
414 internal void SetParent (TreeNode node) {
419 internal string Path {
421 if (path != null) return path;
422 StringBuilder sb = new StringBuilder (index.ToString());
423 TreeNode node = parent;
424 while (node != null) {
426 sb.Insert (0, node.Index.ToString ());
429 path = sb.ToString ();
434 internal bool Populated {
436 object o = ViewState ["Populated"];
437 if (o != null) return (bool) o;
441 ViewState ["Populated"] = value;
445 internal bool HasChildData {
446 get { return nodes != null; }
449 internal void Populate ()
455 tree.NotifyPopulateRequired (this);
458 public void Collapse ()
463 public void CollapseAll ()
465 SetExpandedRec (false, -1);
468 public void Expand ()
473 internal void Expand (int depth)
475 SetExpandedRec (true, depth);
478 public void ExpandAll ()
480 SetExpandedRec (true, -1);
483 void SetExpandedRec (bool expanded, int depth)
486 if (depth == 0) return;
488 foreach (TreeNode nod in ChildNodes)
489 nod.SetExpandedRec (expanded, depth - 1);
492 public void Select ()
497 public void ToggleExpandState ()
499 #if TARGET_JVM //No support for Nullable<bool>.GetValueOrDefault() yet
500 bool? value = Expanded;
501 Expanded = value.HasValue ? !value.Value : true;
503 Expanded = !Expanded.GetValueOrDefault(false);
507 void IStateManager.LoadViewState (object savedState)
509 LoadViewState (savedState);
512 protected virtual void LoadViewState (object savedState)
514 if (savedState == null)
517 object[] states = (object[]) savedState;
518 ViewState.LoadViewState (states [0]);
520 if (tree != null && SelectedFlag)
521 tree.SetSelectedNode (this, true);
523 if (!PopulateOnDemand || Populated)
524 ((IStateManager)ChildNodes).LoadViewState (states [1]);
527 object IStateManager.SaveViewState ()
529 return SaveViewState ();
532 protected virtual object SaveViewState ()
534 object[] states = new object[2];
535 states[0] = ViewState.SaveViewState();
536 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
538 for (int i = 0; i < states.Length; i++) {
539 if (states [i] != null)
545 void IStateManager.TrackViewState ()
550 protected void TrackViewState ()
554 ViewState.TrackViewState();
557 ((IStateManager)nodes).TrackViewState ();
560 bool IStateManager.IsTrackingViewState {
561 get { return IsTrackingViewState; }
564 protected bool IsTrackingViewState
566 get { return marked; }
569 internal void SetDirty ()
571 ViewState.SetDirty (true);
576 public virtual object Clone ()
578 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
579 foreach (DictionaryEntry e in ViewState)
580 nod.ViewState [(string)e.Key] = ((StateItem)e.Value).Value;
582 foreach (TreeNode c in ChildNodes)
583 nod.ChildNodes.Add ((TreeNode)c.Clone ());
588 object ICloneable.Clone () {
592 internal void Bind (IHierarchyData hierarchyData)
594 this.hierarchyData = hierarchyData;
596 DataPath = hierarchyData.Path;
597 dataItem = hierarchyData.Item;
599 TreeNodeBinding bin = GetBinding ();
602 // Bind ImageToolTip property
604 if (bin.ImageToolTipField.Length > 0) {
605 ImageToolTip = Convert.ToString (GetBoundPropertyValue (bin.ImageToolTipField));
606 if (ImageToolTip.Length == 0)
607 ImageToolTip = bin.ImageToolTip;
609 else if (bin.ImageToolTip.Length > 0)
610 ImageToolTip = bin.ImageToolTip;
612 // Bind ImageUrl property
614 if (bin.ImageUrlField.Length > 0) {
615 ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
616 if (ImageUrl.Length == 0)
617 ImageUrl = bin.ImageUrl;
619 else if (bin.ImageUrl.Length > 0)
620 ImageUrl = bin.ImageUrl;
622 // Bind NavigateUrl property
624 if (bin.NavigateUrlField.Length > 0) {
625 NavigateUrl = Convert.ToString (GetBoundPropertyValue (bin.NavigateUrlField));
626 if (NavigateUrl.Length == 0)
627 NavigateUrl = bin.NavigateUrl;
629 else if (bin.NavigateUrl.Length > 0)
630 NavigateUrl = bin.NavigateUrl;
632 // Bind PopulateOnDemand property
634 if (bin.HasPropertyValue ("PopulateOnDemand"))
635 PopulateOnDemand = bin.PopulateOnDemand;
637 // Bind SelectAction property
639 if (bin.HasPropertyValue ("SelectAction"))
640 SelectAction = bin.SelectAction;
642 // Bind ShowCheckBox property
644 if (bin.HasPropertyValue ("ShowCheckBox"))
645 ShowCheckBox = bin.ShowCheckBox;
647 // Bind Target property
649 if (bin.TargetField.Length > 0) {
650 Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
651 if (Target.Length == 0)
654 else if (bin.Target.Length > 0)
657 // Bind Text property
659 if (bin.TextField.Length > 0) {
660 text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
661 if (bin.FormatString.Length > 0)
662 text = string.Format (bin.FormatString, text);
664 if (String.IsNullOrEmpty (text)) {
665 if (bin.Text.Length > 0)
667 else if (bin.Value.Length > 0)
670 if (!String.IsNullOrEmpty (text))
673 // Bind ToolTip property
675 if (bin.ToolTipField.Length > 0) {
676 ToolTip = Convert.ToString (GetBoundPropertyValue (bin.ToolTipField));
677 if (ToolTip.Length == 0)
678 ToolTip = bin.ToolTip;
680 else if (bin.ToolTip.Length > 0)
681 ToolTip = bin.ToolTip;
683 // Bind Value property
685 if (bin.ValueField.Length > 0) {
686 value = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
688 if (String.IsNullOrEmpty (value)) {
689 if (bin.Value.Length > 0)
691 else if (bin.Text.Length > 0)
694 if (!String.IsNullOrEmpty (value))
698 Text = Value = GetDefaultBoundText ();
701 INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
702 if (navigateUIData != null) {
703 SelectAction = TreeNodeSelectAction.None;
704 Text = navigateUIData.ToString ();
705 NavigateUrl = navigateUIData.NavigateUrl;
706 ToolTip = navigateUIData.Description;
710 internal void SetDataItem (object item)
715 internal void SetDataPath (string path)
720 internal void SetDataBound (bool bound)
725 string GetDefaultBoundText ()
727 if (hierarchyData != null) return hierarchyData.ToString ();
728 else if (dataItem != null) return dataItem.ToString ();
729 else return string.Empty;
732 string GetDataItemType ()
734 if (hierarchyData != null) return hierarchyData.Type;
735 else if (dataItem != null) return dataItem.GetType().ToString ();
736 else return string.Empty;
739 internal bool IsParentNode {
740 get { return ChildNodes.Count > 0 || (PopulateOnDemand && !Populated); }
743 internal bool IsLeafNode {
744 get { return !IsParentNode; }
747 internal bool IsRootNode {
748 get { return Depth == 0; }
751 TreeNodeBinding GetBinding ()
753 if (tree == null) return null;
754 if (gotBinding) return binding;
755 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
760 object GetBoundPropertyValue (string name)
762 if (boundProperties == null) {
763 if (hierarchyData != null)
764 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
766 boundProperties = TypeDescriptor.GetProperties (dataItem);
769 PropertyDescriptor prop = boundProperties.Find (name, true);
771 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
773 if (hierarchyData != null)
774 return prop.GetValue (hierarchyData);
776 return prop.GetValue (dataItem);
779 internal void BeginRenderText (HtmlTextWriter writer)
781 RenderPreText (writer);
784 internal void EndRenderText (HtmlTextWriter writer)
786 RenderPostText (writer);
789 protected virtual void RenderPreText (HtmlTextWriter writer)
793 protected virtual void RenderPostText (HtmlTextWriter writer)