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;
56 IHierarchyData hierarchyData;
59 TreeNodeBinding binding;
60 PropertyDescriptorCollection boundProperties;
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;
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 ()
126 internal TreeView Tree {
131 value.SetSelectedNode (this, false);
132 else if (tree != null)
133 tree.SetSelectedNode (null, false);
137 nodes.SetTree (tree);
142 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
143 [DefaultValue (false)]
145 public bool DataBound {
146 get { return dataBound; }
149 [DefaultValue (null)]
151 public object DataItem {
153 if (!dataBound) throw new InvalidOperationException ("TreeNode is not data bound.");
158 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
161 public string DataPath {
163 if (!dataBound) throw new InvalidOperationException ("TreeNode is not data bound.");
165 if (dataPath == null && hierarchyData != null)
166 dataPath = hierarchyData.Path;
172 [DefaultValue (false)]
173 public bool Checked {
175 object o = ViewState ["Checked"];
176 if (o != null) return (bool)o;
180 ViewState ["Checked"] = value;
182 tree.NotifyCheckChanged (this);
186 [DefaultValue (null)]
187 [MergableProperty (false)]
189 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
190 public TreeNodeCollection ChildNodes {
193 if (PopulateOnDemand && tree == null)
196 nodes = new TreeNodeCollection (this);
198 if (IsTrackingViewState)
199 ((IStateManager)nodes).TrackViewState();
201 if (PopulateOnDemand && !Populated) {
210 [DefaultValue (null)]
211 public bool? Expanded {
213 object o = ViewState ["Expanded"];
217 ViewState ["Expanded"] = value;
219 tree.NotifyExpandedChanged (this);
225 public string ImageToolTip {
227 object o = ViewState ["ImageToolTip"];
228 if (o != null) return (string)o;
232 ViewState ["ImageToolTip"] = value;
238 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
239 public string ImageUrl {
241 object o = ViewState ["ImageUrl"];
242 if (o != null) return (string)o;
246 ViewState ["ImageUrl"] = value;
252 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
253 public string NavigateUrl {
255 object o = ViewState ["NavigateUrl"];
256 if (o != null) return (string)o;
260 ViewState ["NavigateUrl"] = value;
264 [DefaultValue (false)]
265 public bool PopulateOnDemand {
267 object o = ViewState ["PopulateOnDemand"];
268 if (o != null) return (bool)o;
272 ViewState ["PopulateOnDemand"] = value;
276 [DefaultValue (TreeNodeSelectAction.Select)]
277 public TreeNodeSelectAction SelectAction {
279 object o = ViewState ["SelectAction"];
280 if (o != null) return (TreeNodeSelectAction)o;
281 return TreeNodeSelectAction.Select;
284 ViewState ["SelectAction"] = value;
288 [DefaultValue (null)]
289 public bool? ShowCheckBox {
291 object o = ViewState ["ShowCheckBox"];
295 ViewState ["ShowCheckBox"] = value;
300 public string Target {
302 object o = ViewState ["Target"];
303 if(o != null) return (string)o;
307 ViewState ["Target"] = value;
313 [WebSysDescription ("The display text of the tree node.")]
316 object o = ViewState ["Text"];
317 if (o != null) return (string)o;
321 ViewState ["Text"] = value;
327 public string ToolTip {
329 object o = ViewState ["ToolTip"];
330 if(o != null) return (string)o;
334 ViewState ["ToolTip"] = value;
340 public string Value {
342 object o = ViewState ["Value"];
343 if(o != null) return (string)o;
347 ViewState ["Value"] = value;
351 [DefaultValue (false)]
352 public bool Selected {
358 if (!value && tree.SelectedNode == this)
359 tree.SetSelectedNode (null, false);
361 tree.SetSelectedNode (this, false);
364 SelectedFlag = value;
368 internal virtual bool SelectedFlag {
370 object o = ViewState ["Selected"];
371 if(o != null) return (bool)o;
375 ViewState ["Selected"] = value;
379 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
381 public TreeNode Parent {
382 get { return parent; }
385 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
387 public string ValuePath {
389 if (tree == null) return Value;
391 StringBuilder sb = new StringBuilder (Value);
392 TreeNode node = parent;
393 while (node != null) {
394 sb.Insert (0, tree.PathSeparator);
395 sb.Insert (0, node.Value);
398 return sb.ToString ();
403 get { return index; }
404 set { index = value; ResetPathData (); }
407 internal void SetParent (TreeNode node) {
412 internal string Path {
414 if (path != null) return path;
415 StringBuilder sb = new StringBuilder (index.ToString());
416 TreeNode node = parent;
417 while (node != null) {
419 sb.Insert (0, node.Index.ToString ());
422 path = sb.ToString ();
427 internal bool Populated {
429 object o = ViewState ["Populated"];
430 if (o != null) return (bool) o;
434 ViewState ["Populated"] = value;
438 internal bool HasChildData {
439 get { return nodes != null; }
442 internal void Populate ()
444 tree.NotifyPopulateRequired (this);
447 public void Collapse ()
452 public void CollapseAll ()
454 SetExpandedRec (false, -1);
457 public void Expand ()
462 internal void Expand (int depth)
464 SetExpandedRec (true, depth);
467 public void ExpandAll ()
469 SetExpandedRec (true, -1);
472 void SetExpandedRec (bool expanded, int depth)
475 if (depth == 0) return;
477 foreach (TreeNode nod in ChildNodes)
478 nod.SetExpandedRec (expanded, depth - 1);
481 public void Select ()
486 public void ToggleExpandState ()
488 #if TARGET_JVM //No support for Nullable<bool>.GetValueOrDefault() yet
489 bool? value = Expanded;
490 Expanded = value.HasValue ? !value.Value : true;
492 Expanded = !Expanded;
496 void IStateManager.LoadViewState (object savedState)
498 LoadViewState (savedState);
501 protected virtual void LoadViewState (object savedState)
503 if (savedState == null)
506 object[] states = (object[]) savedState;
507 ViewState.LoadViewState (states [0]);
509 if (tree != null && SelectedFlag)
510 tree.SetSelectedNode (this, true);
512 if (!PopulateOnDemand || Populated)
513 ((IStateManager)ChildNodes).LoadViewState (states [1]);
516 object IStateManager.SaveViewState ()
518 return SaveViewState ();
521 protected virtual object SaveViewState ()
523 object[] states = new object[2];
524 states[0] = ViewState.SaveViewState();
525 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
527 for (int i = 0; i < states.Length; i++) {
528 if (states [i] != null)
534 void IStateManager.TrackViewState ()
539 protected void TrackViewState ()
543 ViewState.TrackViewState();
546 ((IStateManager)nodes).TrackViewState ();
549 bool IStateManager.IsTrackingViewState {
550 get { return IsTrackingViewState; }
553 protected bool IsTrackingViewState
555 get { return marked; }
558 internal void SetDirty ()
560 ViewState.SetDirty (true);
563 public virtual object Clone ()
565 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
566 foreach (DictionaryEntry e in ViewState)
567 nod.ViewState [(string)e.Key] = e.Value;
569 foreach (TreeNode c in ChildNodes)
570 nod.ChildNodes.Add ((TreeNode)c.Clone ());
575 internal void Bind (IHierarchyData hierarchyData)
577 this.hierarchyData = hierarchyData;
579 dataItem = hierarchyData.Item;
581 TreeNodeBinding bin = GetBinding ();
584 // Bind ImageToolTip property
586 if (bin.ImageToolTipField.Length > 0)
587 ImageToolTip = (string) GetBoundPropertyValue (bin.ImageToolTipField);
588 else if (bin.ImageToolTip.Length > 0)
589 ImageToolTip = bin.ImageToolTip;
591 // Bind ImageUrl property
593 if (bin.ImageUrlField.Length > 0)
594 ImageUrl = (string) GetBoundPropertyValue (bin.ImageUrlField);
595 else if (bin.ImageUrl.Length > 0)
596 ImageUrl = bin.ImageUrl;
598 // Bind NavigateUrl property
600 if (bin.NavigateUrlField.Length > 0)
601 NavigateUrl = (string) GetBoundPropertyValue (bin.NavigateUrlField);
602 else if (bin.NavigateUrl.Length > 0)
603 NavigateUrl = bin.NavigateUrl;
605 // Bind PopulateOnDemand property
607 if (bin.HasPropertyValue ("PopulateOnDemand"))
608 PopulateOnDemand = bin.PopulateOnDemand;
610 // Bind SelectAction property
612 if (bin.HasPropertyValue ("SelectAction"))
613 SelectAction = bin.SelectAction;
615 // Bind ShowCheckBox property
617 if (bin.HasPropertyValue ("ShowCheckBox"))
618 ShowCheckBox = bin.ShowCheckBox;
620 // Bind Target property
622 if (bin.TargetField.Length > 0)
623 Target = (string) GetBoundPropertyValue (bin.TargetField);
624 else if (bin.Target.Length > 0)
627 // Bind Text property
630 if (bin.TextField.Length > 0)
631 text = (string) GetBoundPropertyValue (bin.TextField);
632 else if (bin.Text.Length > 0)
635 text = GetDefaultBoundText ();
637 if (bin.FormatString.Length != 0)
638 text = string.Format (bin.FormatString, text);
641 // Bind ToolTip property
643 if (bin.ToolTipField.Length > 0)
644 ToolTip = (string) GetBoundPropertyValue (bin.ToolTipField);
645 else if (bin.ToolTip.Length > 0)
646 ToolTip = bin.ToolTip;
648 // Bind Value property
650 if (bin.ValueField.Length > 0)
651 Value = (string) GetBoundPropertyValue (bin.ValueField);
652 if (bin.Value.Length > 0)
655 Value = GetDefaultBoundText ();
657 Text = Value = GetDefaultBoundText ();
660 FillBoundChildren ();
663 internal void SetDataItem (object item)
668 internal void SetDataPath (string path)
673 internal void SetDataBound (bool bound)
678 string GetDefaultBoundText ()
680 if (hierarchyData != null) return hierarchyData.ToString ();
681 else if (dataItem != null) return dataItem.ToString ();
682 else return string.Empty;
685 string GetDataItemType ()
687 if (hierarchyData != null) return hierarchyData.Type;
688 else if (dataItem != null) return dataItem.GetType().ToString ();
689 else return string.Empty;
692 internal bool IsParentNode {
693 get { return ChildNodes.Count > 0 && Parent != null; }
696 internal bool IsLeafNode {
697 get { return ChildNodes.Count == 0; }
700 internal bool IsRootNode {
701 get { return ChildNodes.Count > 0 && Parent == null; }
704 TreeNodeBinding GetBinding ()
706 if (tree == null) return null;
707 if (gotBinding) return binding;
708 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
713 object GetBoundPropertyValue (string name)
715 if (boundProperties == null) {
716 if (hierarchyData != null)
717 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
719 boundProperties = TypeDescriptor.GetProperties (dataItem);
722 PropertyDescriptor prop = boundProperties.Find (name, true);
724 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
726 if (hierarchyData != null)
727 return prop.GetValue (hierarchyData);
729 return prop.GetValue (dataItem);
732 void FillBoundChildren ()
734 if (hierarchyData == null || !hierarchyData.HasChildren) return;
735 if (tree.MaxDataBindDepth != -1 && Depth >= tree.MaxDataBindDepth) return;
737 IHierarchicalEnumerable e = hierarchyData.GetChildren ();
738 foreach (object obj in e) {
739 IHierarchyData hdata = e.GetHierarchyData (obj);
740 TreeNode node = tree != null ? tree.CreateNode () : new TreeNode ();
741 ChildNodes.Add (node);
746 internal void BeginRenderText (HtmlTextWriter writer)
748 RenderPreText (writer);
751 internal void EndRenderText (HtmlTextWriter writer)
753 RenderPostText (writer);
756 protected virtual void RenderPreText (HtmlTextWriter writer)
760 protected virtual void RenderPostText (HtmlTextWriter writer)