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"];
320 if (o != null) return (string)o;
324 ViewState ["Text"] = value;
330 public string ToolTip {
332 object o = ViewState ["ToolTip"];
333 if(o != null) return (string)o;
337 ViewState ["ToolTip"] = value;
343 public string Value {
345 object o = ViewState ["Value"];
346 if(o != null) return (string)o;
350 ViewState ["Value"] = value;
354 [DefaultValue (false)]
355 public bool Selected {
360 SelectedFlag = value;
363 if (!value && tree.SelectedNode == this)
364 tree.SetSelectedNode (null, false);
366 tree.SetSelectedNode (this, false);
371 internal virtual bool SelectedFlag {
373 object o = ViewState ["Selected"];
374 if(o != null) return (bool)o;
378 ViewState ["Selected"] = value;
382 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
384 public TreeNode Parent {
385 get { return parent; }
388 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
390 public string ValuePath {
392 if (tree == null) return Value;
394 StringBuilder sb = new StringBuilder (Value);
395 TreeNode node = parent;
396 while (node != null) {
397 sb.Insert (0, tree.PathSeparator);
398 sb.Insert (0, node.Value);
401 return sb.ToString ();
406 get { return index; }
407 set { index = value; ResetPathData (); }
410 internal void SetParent (TreeNode node) {
415 internal string Path {
417 if (path != null) return path;
418 StringBuilder sb = new StringBuilder (index.ToString());
419 TreeNode node = parent;
420 while (node != null) {
422 sb.Insert (0, node.Index.ToString ());
425 path = sb.ToString ();
430 internal bool Populated {
432 object o = ViewState ["Populated"];
433 if (o != null) return (bool) o;
437 ViewState ["Populated"] = value;
441 internal bool HasChildData {
442 get { return nodes != null; }
445 internal void Populate ()
451 tree.NotifyPopulateRequired (this);
454 public void Collapse ()
459 public void CollapseAll ()
461 SetExpandedRec (false, -1);
464 public void Expand ()
469 internal void Expand (int depth)
471 SetExpandedRec (true, depth);
474 public void ExpandAll ()
476 SetExpandedRec (true, -1);
479 void SetExpandedRec (bool expanded, int depth)
482 if (depth == 0) return;
484 foreach (TreeNode nod in ChildNodes)
485 nod.SetExpandedRec (expanded, depth - 1);
488 public void Select ()
493 public void ToggleExpandState ()
495 #if TARGET_JVM //No support for Nullable<bool>.GetValueOrDefault() yet
496 bool? value = Expanded;
497 Expanded = value.HasValue ? !value.Value : true;
499 Expanded = !Expanded.GetValueOrDefault(false);
503 void IStateManager.LoadViewState (object savedState)
505 LoadViewState (savedState);
508 protected virtual void LoadViewState (object savedState)
510 if (savedState == null)
513 object[] states = (object[]) savedState;
514 ViewState.LoadViewState (states [0]);
516 if (tree != null && SelectedFlag)
517 tree.SetSelectedNode (this, true);
519 if (!PopulateOnDemand || Populated)
520 ((IStateManager)ChildNodes).LoadViewState (states [1]);
523 object IStateManager.SaveViewState ()
525 return SaveViewState ();
528 protected virtual object SaveViewState ()
530 object[] states = new object[2];
531 states[0] = ViewState.SaveViewState();
532 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
534 for (int i = 0; i < states.Length; i++) {
535 if (states [i] != null)
541 void IStateManager.TrackViewState ()
546 protected void TrackViewState ()
550 ViewState.TrackViewState();
553 ((IStateManager)nodes).TrackViewState ();
556 bool IStateManager.IsTrackingViewState {
557 get { return IsTrackingViewState; }
560 protected bool IsTrackingViewState
562 get { return marked; }
565 internal void SetDirty ()
567 ViewState.SetDirty (true);
572 public virtual object Clone ()
574 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
575 foreach (DictionaryEntry e in ViewState)
576 nod.ViewState [(string)e.Key] = ((StateItem)e.Value).Value;
578 foreach (TreeNode c in ChildNodes)
579 nod.ChildNodes.Add ((TreeNode)c.Clone ());
584 object ICloneable.Clone () {
588 internal void Bind (IHierarchyData hierarchyData)
590 this.hierarchyData = hierarchyData;
592 DataPath = hierarchyData.Path;
593 dataItem = hierarchyData.Item;
595 TreeNodeBinding bin = GetBinding ();
598 // Bind ImageToolTip property
600 if (bin.ImageToolTipField.Length > 0) {
601 ImageToolTip = Convert.ToString (GetBoundPropertyValue (bin.ImageToolTipField));
602 if (ImageToolTip.Length == 0)
603 ImageToolTip = bin.ImageToolTip;
605 else if (bin.ImageToolTip.Length > 0)
606 ImageToolTip = bin.ImageToolTip;
608 // Bind ImageUrl property
610 if (bin.ImageUrlField.Length > 0) {
611 ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
612 if (ImageUrl.Length == 0)
613 ImageUrl = bin.ImageUrl;
615 else if (bin.ImageUrl.Length > 0)
616 ImageUrl = bin.ImageUrl;
618 // Bind NavigateUrl property
620 if (bin.NavigateUrlField.Length > 0) {
621 NavigateUrl = Convert.ToString (GetBoundPropertyValue (bin.NavigateUrlField));
622 if (NavigateUrl.Length == 0)
623 NavigateUrl = bin.NavigateUrl;
625 else if (bin.NavigateUrl.Length > 0)
626 NavigateUrl = bin.NavigateUrl;
628 // Bind PopulateOnDemand property
630 if (bin.HasPropertyValue ("PopulateOnDemand"))
631 PopulateOnDemand = bin.PopulateOnDemand;
633 // Bind SelectAction property
635 if (bin.HasPropertyValue ("SelectAction"))
636 SelectAction = bin.SelectAction;
638 // Bind ShowCheckBox property
640 if (bin.HasPropertyValue ("ShowCheckBox"))
641 ShowCheckBox = bin.ShowCheckBox;
643 // Bind Target property
645 if (bin.TargetField.Length > 0) {
646 Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
647 if (Target.Length == 0)
650 else if (bin.Target.Length > 0)
653 // Bind Text property
655 if (bin.TextField.Length > 0) {
656 Text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
657 if (bin.FormatString.Length > 0)
658 Text = string.Format (bin.FormatString, Text);
659 if (Text.Length == 0)
661 if (Text.Length == 0)
663 if (Text.Length == 0 && bin.ValueField.Length > 0)
664 Text = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
666 else if (bin.Text.Length > 0)
668 else if (bin.Value.Length > 0)
671 Text = GetDefaultBoundText ();
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));
687 if (Value.Length == 0)
689 if (Value.Length == 0)
691 if(Value.Length == 0 && bin.TextField.Length > 0)
692 Value = Convert.ToString (GetBoundPropertyValue (bin.TextField));
694 else if (bin.Value.Length > 0)
696 else if (bin.Text.Length > 0)
698 else if (Text.Length > 0)
701 Value = GetDefaultBoundText ();
703 Text = Value = GetDefaultBoundText ();
706 INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
707 if (navigateUIData != null) {
708 Text = navigateUIData.ToString ();
709 NavigateUrl = navigateUIData.NavigateUrl;
713 internal void SetDataItem (object item)
718 internal void SetDataPath (string path)
723 internal void SetDataBound (bool bound)
728 string GetDefaultBoundText ()
730 if (hierarchyData != null) return hierarchyData.ToString ();
731 else if (dataItem != null) return dataItem.ToString ();
732 else return string.Empty;
735 string GetDataItemType ()
737 if (hierarchyData != null) return hierarchyData.Type;
738 else if (dataItem != null) return dataItem.GetType().ToString ();
739 else return string.Empty;
742 internal bool IsParentNode {
743 get { return ChildNodes.Count > 0 || (PopulateOnDemand && !Populated); }
746 internal bool IsLeafNode {
747 get { return !IsParentNode; }
750 internal bool IsRootNode {
751 get { return Depth == 0; }
754 TreeNodeBinding GetBinding ()
756 if (tree == null) return null;
757 if (gotBinding) return binding;
758 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
763 object GetBoundPropertyValue (string name)
765 if (boundProperties == null) {
766 if (hierarchyData != null)
767 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
769 boundProperties = TypeDescriptor.GetProperties (dataItem);
772 PropertyDescriptor prop = boundProperties.Find (name, true);
774 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
776 if (hierarchyData != null)
777 return prop.GetValue (hierarchyData);
779 return prop.GetValue (dataItem);
782 internal void BeginRenderText (HtmlTextWriter writer)
784 RenderPreText (writer);
787 internal void EndRenderText (HtmlTextWriter writer)
789 RenderPostText (writer);
792 protected virtual void RenderPreText (HtmlTextWriter writer)
796 protected virtual void RenderPostText (HtmlTextWriter writer)