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;
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);
130 else if (tree != null)
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 ViewState ["Expanded"] = value;
205 tree.NotifyExpandedChanged (this);
206 if (PopulateOnDemand && !Populated && value.HasValue && value.Value)
213 public string ImageToolTip {
215 object o = ViewState ["ImageToolTip"];
216 if (o != null) return (string)o;
220 ViewState ["ImageToolTip"] = value;
226 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
227 public string ImageUrl {
229 object o = ViewState ["ImageUrl"];
230 if (o != null) return (string)o;
234 ViewState ["ImageUrl"] = value;
240 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
241 public string NavigateUrl {
243 object o = ViewState ["NavigateUrl"];
244 if (o != null) return (string)o;
248 ViewState ["NavigateUrl"] = value;
252 [DefaultValue (false)]
253 public bool PopulateOnDemand {
255 object o = ViewState ["PopulateOnDemand"];
256 if (o != null) return (bool)o;
260 ViewState ["PopulateOnDemand"] = value;
264 [DefaultValue (TreeNodeSelectAction.Select)]
265 public TreeNodeSelectAction SelectAction {
267 object o = ViewState ["SelectAction"];
268 if (o != null) return (TreeNodeSelectAction)o;
269 return TreeNodeSelectAction.Select;
272 ViewState ["SelectAction"] = value;
276 [DefaultValue (null)]
277 public bool? ShowCheckBox {
279 object o = ViewState ["ShowCheckBox"];
283 ViewState ["ShowCheckBox"] = value;
288 public string Target {
290 object o = ViewState ["Target"];
291 if(o != null) return (string)o;
295 ViewState ["Target"] = value;
301 [WebSysDescription ("The display text of the tree node.")]
304 object o = ViewState ["Text"];
305 if (o != null) return (string)o;
309 ViewState ["Text"] = value;
315 public string ToolTip {
317 object o = ViewState ["ToolTip"];
318 if(o != null) return (string)o;
322 ViewState ["ToolTip"] = value;
328 public string Value {
330 object o = ViewState ["Value"];
331 if(o != null) return (string)o;
335 ViewState ["Value"] = value;
339 [DefaultValue (false)]
340 public bool Selected {
346 if (!value && tree.SelectedNode == this)
347 tree.SetSelectedNode (null, false);
349 tree.SetSelectedNode (this, false);
352 SelectedFlag = value;
356 internal virtual bool SelectedFlag {
358 object o = ViewState ["Selected"];
359 if(o != null) return (bool)o;
363 ViewState ["Selected"] = value;
367 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
369 public TreeNode Parent {
370 get { return parent; }
373 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
375 public string ValuePath {
377 if (tree == null) return Value;
379 StringBuilder sb = new StringBuilder (Value);
380 TreeNode node = parent;
381 while (node != null) {
382 sb.Insert (0, tree.PathSeparator);
383 sb.Insert (0, node.Value);
386 return sb.ToString ();
391 get { return index; }
392 set { index = value; ResetPathData (); }
395 internal void SetParent (TreeNode node) {
400 internal string Path {
402 if (path != null) return path;
403 StringBuilder sb = new StringBuilder (index.ToString());
404 TreeNode node = parent;
405 while (node != null) {
407 sb.Insert (0, node.Index.ToString ());
410 path = sb.ToString ();
415 internal bool Populated {
417 object o = ViewState ["Populated"];
418 if (o != null) return (bool) o;
422 ViewState ["Populated"] = value;
426 internal bool HasChildData {
427 get { return nodes != null; }
430 internal void Populate ()
436 tree.NotifyPopulateRequired (this);
439 public void Collapse ()
444 public void CollapseAll ()
446 SetExpandedRec (false, -1);
449 public void Expand ()
454 internal void Expand (int depth)
456 SetExpandedRec (true, depth);
459 public void ExpandAll ()
461 SetExpandedRec (true, -1);
464 void SetExpandedRec (bool expanded, int depth)
467 if (depth == 0) return;
469 foreach (TreeNode nod in ChildNodes)
470 nod.SetExpandedRec (expanded, depth - 1);
473 public void Select ()
478 public void ToggleExpandState ()
480 #if TARGET_JVM //No support for Nullable<bool>.GetValueOrDefault() yet
481 bool? value = Expanded;
482 Expanded = value.HasValue ? !value.Value : true;
484 Expanded = !Expanded.GetValueOrDefault(false);
488 void IStateManager.LoadViewState (object savedState)
490 LoadViewState (savedState);
493 protected virtual void LoadViewState (object savedState)
495 if (savedState == null)
498 object[] states = (object[]) savedState;
499 ViewState.LoadViewState (states [0]);
501 if (tree != null && SelectedFlag)
502 tree.SetSelectedNode (this, true);
504 if (!PopulateOnDemand || Populated)
505 ((IStateManager)ChildNodes).LoadViewState (states [1]);
508 object IStateManager.SaveViewState ()
510 return SaveViewState ();
513 protected virtual object SaveViewState ()
515 object[] states = new object[2];
516 states[0] = ViewState.SaveViewState();
517 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
519 for (int i = 0; i < states.Length; i++) {
520 if (states [i] != null)
526 void IStateManager.TrackViewState ()
531 protected void TrackViewState ()
535 ViewState.TrackViewState();
538 ((IStateManager)nodes).TrackViewState ();
541 bool IStateManager.IsTrackingViewState {
542 get { return IsTrackingViewState; }
545 protected bool IsTrackingViewState
547 get { return marked; }
550 internal void SetDirty ()
552 ViewState.SetDirty (true);
557 public virtual object Clone ()
559 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
560 foreach (DictionaryEntry e in ViewState)
561 nod.ViewState [(string)e.Key] = ((StateItem)e.Value).Value;
563 foreach (TreeNode c in ChildNodes)
564 nod.ChildNodes.Add ((TreeNode)c.Clone ());
569 internal void Bind (IHierarchyData hierarchyData)
571 this.hierarchyData = hierarchyData;
573 DataPath = hierarchyData.Path;
574 dataItem = hierarchyData.Item;
576 TreeNodeBinding bin = GetBinding ();
579 // Bind ImageToolTip property
581 if (bin.ImageToolTipField.Length > 0) {
582 ImageToolTip = Convert.ToString (GetBoundPropertyValue (bin.ImageToolTipField));
583 if (ImageToolTip.Length == 0)
584 ImageToolTip = bin.ImageToolTip;
586 else if (bin.ImageToolTip.Length > 0)
587 ImageToolTip = bin.ImageToolTip;
589 // Bind ImageUrl property
591 if (bin.ImageUrlField.Length > 0) {
592 ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
593 if (ImageUrl.Length == 0)
594 ImageUrl = bin.ImageUrl;
596 else if (bin.ImageUrl.Length > 0)
597 ImageUrl = bin.ImageUrl;
599 // Bind NavigateUrl property
601 if (bin.NavigateUrlField.Length > 0) {
602 NavigateUrl = Convert.ToString (GetBoundPropertyValue (bin.NavigateUrlField));
603 if (NavigateUrl.Length == 0)
604 NavigateUrl = bin.NavigateUrl;
606 else if (bin.NavigateUrl.Length > 0)
607 NavigateUrl = bin.NavigateUrl;
609 // Bind PopulateOnDemand property
611 if (bin.HasPropertyValue ("PopulateOnDemand"))
612 PopulateOnDemand = bin.PopulateOnDemand;
614 // Bind SelectAction property
616 if (bin.HasPropertyValue ("SelectAction"))
617 SelectAction = bin.SelectAction;
619 // Bind ShowCheckBox property
621 if (bin.HasPropertyValue ("ShowCheckBox"))
622 ShowCheckBox = bin.ShowCheckBox;
624 // Bind Target property
626 if (bin.TargetField.Length > 0) {
627 Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
628 if (Target.Length == 0)
631 else if (bin.Target.Length > 0)
634 // Bind Text property
636 if (bin.TextField.Length > 0) {
637 Text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
638 if (bin.FormatString.Length > 0)
639 Text = string.Format (bin.FormatString, Text);
640 if (Text.Length == 0)
642 if (Text.Length == 0)
644 if (Text.Length == 0 && bin.ValueField.Length > 0)
645 Text = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
647 else if (bin.Text.Length > 0)
649 else if (bin.Value.Length > 0)
652 Text = GetDefaultBoundText ();
654 // Bind ToolTip property
656 if (bin.ToolTipField.Length > 0) {
657 ToolTip = Convert.ToString (GetBoundPropertyValue (bin.ToolTipField));
658 if (ToolTip.Length == 0)
659 ToolTip = bin.ToolTip;
661 else if (bin.ToolTip.Length > 0)
662 ToolTip = bin.ToolTip;
664 // Bind Value property
666 if (bin.ValueField.Length > 0) {
667 Value = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
668 if (Value.Length == 0)
670 if (Value.Length == 0)
672 if(Value.Length == 0 && bin.TextField.Length > 0)
673 Value = Convert.ToString (GetBoundPropertyValue (bin.TextField));
675 else if (bin.Value.Length > 0)
677 else if (bin.Text.Length > 0)
680 Value = GetDefaultBoundText ();
682 Text = Value = GetDefaultBoundText ();
686 internal void SetDataItem (object item)
691 internal void SetDataPath (string path)
696 internal void SetDataBound (bool bound)
701 string GetDefaultBoundText ()
703 if (hierarchyData != null) return hierarchyData.ToString ();
704 else if (dataItem != null) return dataItem.ToString ();
705 else return string.Empty;
708 string GetDataItemType ()
710 if (hierarchyData != null) return hierarchyData.Type;
711 else if (dataItem != null) return dataItem.GetType().ToString ();
712 else return string.Empty;
715 internal bool IsParentNode {
716 get { return ChildNodes.Count > 0 || (PopulateOnDemand && !Populated); }
719 internal bool IsLeafNode {
720 get { return !IsParentNode; }
723 internal bool IsRootNode {
724 get { return Depth == 0; }
727 TreeNodeBinding GetBinding ()
729 if (tree == null) return null;
730 if (gotBinding) return binding;
731 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
736 object GetBoundPropertyValue (string name)
738 if (boundProperties == null) {
739 if (hierarchyData != null)
740 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
742 boundProperties = TypeDescriptor.GetProperties (dataItem);
745 PropertyDescriptor prop = boundProperties.Find (name, true);
747 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
749 if (hierarchyData != null)
750 return prop.GetValue (hierarchyData);
752 return prop.GetValue (dataItem);
755 internal void BeginRenderText (HtmlTextWriter writer)
757 RenderPreText (writer);
760 internal void EndRenderText (HtmlTextWriter writer)
762 RenderPostText (writer);
765 protected virtual void RenderPreText (HtmlTextWriter writer)
769 protected virtual void RenderPostText (HtmlTextWriter writer)