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)
33 using System.Collections;
35 using System.ComponentModel;
38 namespace System.Web.UI.WebControls
40 [ParseChildrenAttribute (true, "ChildNodes")]
41 public class TreeNode: IStateManager, ICloneable
43 StateBag ViewState = new StateBag ();
44 TreeNodeCollection nodes;
53 IHierarchyData hierarchyData;
56 TreeNodeBinding binding;
57 PropertyDescriptorCollection boundProperties;
59 bool hadChildrenBeforePopulating;
61 internal TreeNode (TreeView tree)
70 public TreeNode (string text)
75 public TreeNode (string text, string value)
81 public TreeNode (string text, string value, string imageUrl)
88 public TreeNode (string text, string value, string imageUrl, string navigateUrl, string target)
93 NavigateUrl = navigateUrl;
97 [MonoTODO ("Not implemented")]
98 protected TreeNode (TreeView owner, bool isRoot)
100 throw new NotImplementedException ();
103 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
107 if (depth != -1) return depth;
109 TreeNode nod = parent;
110 while (nod != null) {
118 void ResetPathData ()
124 foreach (TreeNode node in nodes)
125 node.ResetPathData ();
129 internal TreeView Tree {
134 value.SetSelectedNode (this, false);
138 nodes.SetTree (tree);
140 if (PopulateOnDemand && !Populated && Expanded.HasValue && Expanded.Value)
145 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
146 [DefaultValue (false)]
148 public bool DataBound {
149 get { return ViewState ["DataBound"] == null ? false : (bool) ViewState ["DataBound"]; }
150 private set { ViewState ["DataBound"] = value; }
153 [DefaultValue (null)]
155 public object DataItem {
156 get { return dataItem; }
159 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
162 public string DataPath {
163 get { return ViewState ["DataPath"] == null ? String.Empty : (String) ViewState ["DataPath"]; }
164 private set { ViewState ["DataPath"] = value; }
167 [DefaultValue (false)]
168 public bool Checked {
170 object o = ViewState ["Checked"];
171 if (o != null) return (bool)o;
175 ViewState ["Checked"] = value;
177 tree.NotifyCheckChanged (this);
181 [DefaultValue (null)]
182 [MergableProperty (false)]
184 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
185 public TreeNodeCollection ChildNodes {
188 nodes = new TreeNodeCollection (this);
190 if (IsTrackingViewState)
191 ((IStateManager)nodes).TrackViewState();
197 [DefaultValue (null)]
198 public bool? Expanded {
200 object o = ViewState ["Expanded"];
204 bool? current = (bool?) ViewState ["Expanded"];
205 if (current == value)
207 ViewState ["Expanded"] = value;
209 tree.NotifyExpandedChanged (this);
210 if (PopulateOnDemand && !Populated && value.HasValue && value.Value)
217 public string ImageToolTip {
219 object o = ViewState ["ImageToolTip"];
224 set { 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"];
237 set { ViewState ["ImageUrl"] = value; }
242 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
243 public string NavigateUrl {
245 object o = ViewState ["NavigateUrl"];
250 set { ViewState ["NavigateUrl"] = value; }
253 internal bool HadChildrenBeforePopulating {
254 get { return hadChildrenBeforePopulating; }
259 hadChildrenBeforePopulating = value;
263 [DefaultValue (false)]
264 public bool PopulateOnDemand {
266 object o = ViewState ["PopulateOnDemand"];
272 ViewState ["PopulateOnDemand"] = value;
273 if (value && nodes != null && nodes.Count > 0)
274 HadChildrenBeforePopulating = true;
276 HadChildrenBeforePopulating = false;
280 [DefaultValue (TreeNodeSelectAction.Select)]
281 public TreeNodeSelectAction SelectAction {
283 object o = ViewState ["SelectAction"];
285 return (TreeNodeSelectAction)o;
286 return TreeNodeSelectAction.Select;
288 set { ViewState ["SelectAction"] = value; }
291 [DefaultValue (null)]
292 public bool? ShowCheckBox {
294 object o = ViewState ["ShowCheckBox"];
297 set { ViewState ["ShowCheckBox"] = value; }
300 internal bool ShowCheckBoxInternal {
302 if (ShowCheckBox.HasValue)
303 return ShowCheckBox.Value;
305 return (Tree.ShowCheckBoxes == TreeNodeTypes.All) ||
306 ((Tree.ShowCheckBoxes & TreeNodeTypes.Leaf) > 0 && IsLeafNode) ||
307 ((Tree.ShowCheckBoxes & TreeNodeTypes.Parent) > 0 && IsParentNode && Parent != null) ||
308 ((Tree.ShowCheckBoxes & TreeNodeTypes.Root) > 0 && Parent == null && ChildNodes.Count > 0);
313 public string Target {
315 object o = ViewState ["Target"];
320 set { ViewState ["Target"] = value; }
325 [WebSysDescription ("The display text of the tree node.")]
328 object o = ViewState ["Text"];
330 o = ViewState ["Value"];
335 set { ViewState ["Text"] = value; }
340 public string ToolTip {
342 object o = ViewState ["ToolTip"];
347 set { ViewState ["ToolTip"] = value; }
352 public string Value {
354 object o = ViewState ["Value"];
356 o = ViewState ["Text"];
361 set { ViewState ["Value"] = value; }
364 [DefaultValue (false)]
365 public bool Selected {
366 get { return SelectedFlag; }
368 SelectedFlag = value;
371 if (!value && tree.SelectedNode == this)
372 tree.SetSelectedNode (null, false);
374 tree.SetSelectedNode (this, false);
379 internal virtual bool SelectedFlag {
381 object o = ViewState ["Selected"];
386 set { ViewState ["Selected"] = value; }
389 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
391 public TreeNode Parent {
392 get { return parent; }
395 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
397 public string ValuePath {
399 if (tree == null) return Value;
401 StringBuilder sb = new StringBuilder (Value);
402 TreeNode node = parent;
403 while (node != null) {
404 sb.Insert (0, tree.PathSeparator);
405 sb.Insert (0, node.Value);
408 return sb.ToString ();
413 get { return index; }
414 set { index = value; ResetPathData (); }
417 internal void SetParent (TreeNode node)
423 internal string Path {
427 StringBuilder sb = new StringBuilder (index.ToString());
428 TreeNode node = parent;
429 while (node != null) {
431 sb.Insert (0, node.Index.ToString ());
434 path = sb.ToString ();
439 internal bool Populated {
441 object o = ViewState ["Populated"];
446 set { ViewState ["Populated"] = value; }
449 internal bool HasChildData {
450 get { return nodes != null; }
453 internal void Populate ()
459 tree.NotifyPopulateRequired (this);
464 public void Collapse ()
469 public void CollapseAll ()
471 SetExpandedRec (false, -1);
474 public void Expand ()
479 internal void Expand (int depth)
481 SetExpandedRec (true, depth);
484 public void ExpandAll ()
486 SetExpandedRec (true, -1);
489 void SetExpandedRec (bool expanded, int depth)
495 foreach (TreeNode nod in ChildNodes)
496 nod.SetExpandedRec (expanded, depth - 1);
499 public void Select ()
504 public void ToggleExpandState ()
506 Expanded = !Expanded.GetValueOrDefault(false);
509 void IStateManager.LoadViewState (object state)
511 LoadViewState (state);
514 protected virtual void LoadViewState (object state)
519 object[] states = (object[]) state;
520 ViewState.LoadViewState (states [0]);
522 if (tree != null && SelectedFlag)
523 tree.SetSelectedNode (this, true);
525 if (!PopulateOnDemand || Populated)
526 ((IStateManager)ChildNodes).LoadViewState (states [1]);
529 object IStateManager.SaveViewState ()
531 return SaveViewState ();
534 protected virtual object SaveViewState ()
536 object[] states = new object[2];
537 states[0] = ViewState.SaveViewState();
538 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
540 for (int i = 0; i < states.Length; i++) {
541 if (states [i] != null)
547 void IStateManager.TrackViewState ()
552 protected void TrackViewState ()
556 ViewState.TrackViewState();
559 ((IStateManager)nodes).TrackViewState ();
562 bool IStateManager.IsTrackingViewState {
563 get { return IsTrackingViewState; }
566 protected bool IsTrackingViewState {
567 get { return marked; }
570 internal void SetDirty ()
572 ViewState.SetDirty (true);
577 public virtual object Clone ()
579 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
580 foreach (DictionaryEntry e in ViewState)
581 nod.ViewState [(string)e.Key] = ((StateItem)e.Value).Value;
583 foreach (TreeNode c in ChildNodes)
584 nod.ChildNodes.Add ((TreeNode)c.Clone ());
589 object ICloneable.Clone ()
594 internal void Bind (IHierarchyData hierarchyData)
596 this.hierarchyData = hierarchyData;
598 DataPath = hierarchyData.Path;
599 dataItem = hierarchyData.Item;
601 TreeNodeBinding bin = GetBinding ();
604 // Bind ImageToolTip property
606 if (bin.ImageToolTipField.Length > 0) {
607 ImageToolTip = Convert.ToString (GetBoundPropertyValue (bin.ImageToolTipField));
608 if (ImageToolTip.Length == 0)
609 ImageToolTip = bin.ImageToolTip;
610 } else if (bin.ImageToolTip.Length > 0)
611 ImageToolTip = bin.ImageToolTip;
613 // Bind ImageUrl property
615 if (bin.ImageUrlField.Length > 0) {
616 ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
617 if (ImageUrl.Length == 0)
618 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;
628 } else if (bin.NavigateUrl.Length > 0)
629 NavigateUrl = bin.NavigateUrl;
631 // Bind PopulateOnDemand property
633 if (bin.HasPropertyValue ("PopulateOnDemand"))
634 PopulateOnDemand = bin.PopulateOnDemand;
636 // Bind SelectAction property
638 if (bin.HasPropertyValue ("SelectAction"))
639 SelectAction = bin.SelectAction;
641 // Bind ShowCheckBox property
643 if (bin.HasPropertyValue ("ShowCheckBox"))
644 ShowCheckBox = bin.ShowCheckBox;
646 // Bind Target property
648 if (bin.TargetField.Length > 0) {
649 Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
650 if (Target.Length == 0)
652 } else if (bin.Target.Length > 0)
655 // Bind Text property
657 if (bin.TextField.Length > 0) {
658 text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
659 if (bin.FormatString.Length > 0)
660 text = string.Format (bin.FormatString, text);
662 if (String.IsNullOrEmpty (text)) {
663 if (bin.Text.Length > 0)
665 else if (bin.Value.Length > 0)
668 if (!String.IsNullOrEmpty (text))
671 // Bind ToolTip property
673 if (bin.ToolTipField.Length > 0) {
674 ToolTip = Convert.ToString (GetBoundPropertyValue (bin.ToolTipField));
675 if (ToolTip.Length == 0)
676 ToolTip = bin.ToolTip;
677 } else if (bin.ToolTip.Length > 0)
678 ToolTip = bin.ToolTip;
680 // Bind Value property
682 if (bin.ValueField.Length > 0) {
683 value = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
685 if (String.IsNullOrEmpty (value)) {
686 if (bin.Value.Length > 0)
688 else if (bin.Text.Length > 0)
691 if (!String.IsNullOrEmpty (value))
694 Text = Value = GetDefaultBoundText ();
697 INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
698 if (navigateUIData != null) {
699 SelectAction = TreeNodeSelectAction.None;
700 Text = navigateUIData.ToString ();
701 NavigateUrl = navigateUIData.NavigateUrl;
702 ToolTip = navigateUIData.Description;
706 internal void SetDataItem (object item)
711 internal void SetDataPath (string path)
716 internal void SetDataBound (bool bound)
721 string GetDefaultBoundText ()
723 if (hierarchyData != null)
724 return hierarchyData.ToString ();
725 else if (dataItem != null)
726 return dataItem.ToString ();
731 string GetDataItemType ()
733 if (hierarchyData != null)
734 return hierarchyData.Type;
735 else if (dataItem != null)
736 return dataItem.GetType().ToString ();
741 internal bool IsParentNode {
742 get { return ChildNodes.Count > 0 || (PopulateOnDemand && !Populated); }
745 internal bool IsLeafNode {
746 get { return !IsParentNode; }
749 internal bool IsRootNode {
750 get { return Depth == 0; }
753 TreeNodeBinding GetBinding ()
759 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
764 object GetBoundPropertyValue (string name)
766 if (boundProperties == null) {
767 if (hierarchyData != null)
768 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
770 boundProperties = TypeDescriptor.GetProperties (dataItem);
773 PropertyDescriptor prop = boundProperties.Find (name, true);
775 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
777 if (hierarchyData != null)
778 return prop.GetValue (hierarchyData);
780 return prop.GetValue (dataItem);
783 internal void BeginRenderText (HtmlTextWriter writer)
785 RenderPreText (writer);
788 internal void EndRenderText (HtmlTextWriter writer)
790 RenderPostText (writer);
793 protected virtual void RenderPreText (HtmlTextWriter writer)
797 protected virtual void RenderPostText (HtmlTextWriter writer)