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 Expanded = !Expanded;
491 void IStateManager.LoadViewState (object savedState)
493 LoadViewState (savedState);
496 protected virtual void LoadViewState (object savedState)
498 if (savedState == null)
501 object[] states = (object[]) savedState;
502 ViewState.LoadViewState (states [0]);
504 if (tree != null && SelectedFlag)
505 tree.SetSelectedNode (this, true);
507 if (!PopulateOnDemand || Populated)
508 ((IStateManager)ChildNodes).LoadViewState (states [1]);
511 object IStateManager.SaveViewState ()
513 return SaveViewState ();
516 protected virtual object SaveViewState ()
518 object[] states = new object[2];
519 states[0] = ViewState.SaveViewState();
520 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
522 for (int i = 0; i < states.Length; i++) {
523 if (states [i] != null)
529 void IStateManager.TrackViewState ()
534 protected void TrackViewState ()
538 ViewState.TrackViewState();
541 ((IStateManager)nodes).TrackViewState ();
544 bool IStateManager.IsTrackingViewState {
545 get { return IsTrackingViewState; }
548 protected bool IsTrackingViewState
550 get { return marked; }
553 internal void SetDirty ()
555 ViewState.SetDirty (true);
558 public virtual object Clone ()
560 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
561 foreach (DictionaryEntry e in ViewState)
562 nod.ViewState [(string)e.Key] = e.Value;
564 foreach (TreeNode c in ChildNodes)
565 nod.ChildNodes.Add ((TreeNode)c.Clone ());
570 internal void Bind (IHierarchyData hierarchyData)
572 this.hierarchyData = hierarchyData;
574 dataItem = hierarchyData.Item;
576 TreeNodeBinding bin = GetBinding ();
579 // Bind ImageToolTip property
581 if (bin.ImageToolTipField.Length > 0)
582 ImageToolTip = (string) GetBoundPropertyValue (bin.ImageToolTipField);
583 else if (bin.ImageToolTip.Length > 0)
584 ImageToolTip = bin.ImageToolTip;
586 // Bind ImageUrl property
588 if (bin.ImageUrlField.Length > 0)
589 ImageUrl = (string) GetBoundPropertyValue (bin.ImageUrlField);
590 else if (bin.ImageUrl.Length > 0)
591 ImageUrl = bin.ImageUrl;
593 // Bind NavigateUrl property
595 if (bin.NavigateUrlField.Length > 0)
596 NavigateUrl = (string) GetBoundPropertyValue (bin.NavigateUrlField);
597 else if (bin.NavigateUrl.Length > 0)
598 NavigateUrl = bin.NavigateUrl;
600 // Bind PopulateOnDemand property
602 if (bin.HasPropertyValue ("PopulateOnDemand"))
603 PopulateOnDemand = bin.PopulateOnDemand;
605 // Bind SelectAction property
607 if (bin.HasPropertyValue ("SelectAction"))
608 SelectAction = bin.SelectAction;
610 // Bind ShowCheckBox property
612 if (bin.HasPropertyValue ("ShowCheckBox"))
613 ShowCheckBox = bin.ShowCheckBox;
615 // Bind Target property
617 if (bin.TargetField.Length > 0)
618 Target = (string) GetBoundPropertyValue (bin.TargetField);
619 else if (bin.Target.Length > 0)
622 // Bind Text property
625 if (bin.TextField.Length > 0)
626 text = (string) GetBoundPropertyValue (bin.TextField);
627 else if (bin.Text.Length > 0)
630 text = GetDefaultBoundText ();
632 if (bin.FormatString.Length != 0)
633 text = string.Format (bin.FormatString, text);
636 // Bind ToolTip property
638 if (bin.ToolTipField.Length > 0)
639 ToolTip = (string) GetBoundPropertyValue (bin.ToolTipField);
640 else if (bin.ToolTip.Length > 0)
641 ToolTip = bin.ToolTip;
643 // Bind Value property
645 if (bin.ValueField.Length > 0)
646 Value = (string) GetBoundPropertyValue (bin.ValueField);
647 if (bin.Value.Length > 0)
650 Value = GetDefaultBoundText ();
652 Text = Value = GetDefaultBoundText ();
655 FillBoundChildren ();
658 internal void SetDataItem (object item)
663 internal void SetDataPath (string path)
668 internal void SetDataBound (bool bound)
673 string GetDefaultBoundText ()
675 if (hierarchyData != null) return hierarchyData.ToString ();
676 else if (dataItem != null) return dataItem.ToString ();
677 else return string.Empty;
680 string GetDataItemType ()
682 if (hierarchyData != null) return hierarchyData.Type;
683 else if (dataItem != null) return dataItem.GetType().ToString ();
684 else return string.Empty;
687 internal bool IsParentNode {
688 get { return ChildNodes.Count > 0 && Parent != null; }
691 internal bool IsLeafNode {
692 get { return ChildNodes.Count == 0; }
695 internal bool IsRootNode {
696 get { return ChildNodes.Count > 0 && Parent == null; }
699 TreeNodeBinding GetBinding ()
701 if (tree == null) return null;
702 if (gotBinding) return binding;
703 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
708 object GetBoundPropertyValue (string name)
710 if (boundProperties == null) {
711 if (hierarchyData != null)
712 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
714 boundProperties = TypeDescriptor.GetProperties (dataItem);
717 PropertyDescriptor prop = boundProperties.Find (name, true);
719 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
721 if (hierarchyData != null)
722 return prop.GetValue (hierarchyData);
724 return prop.GetValue (dataItem);
727 void FillBoundChildren ()
729 if (hierarchyData == null || !hierarchyData.HasChildren) return;
730 if (tree.MaxDataBindDepth != -1 && Depth >= tree.MaxDataBindDepth) return;
732 IHierarchicalEnumerable e = hierarchyData.GetChildren ();
733 foreach (object obj in e) {
734 IHierarchyData hdata = e.GetHierarchyData (obj);
735 TreeNode node = tree != null ? tree.CreateNode () : new TreeNode ();
736 ChildNodes.Add (node);
741 internal void BeginRenderText (HtmlTextWriter writer)
743 RenderPreText (writer);
746 internal void EndRenderText (HtmlTextWriter writer)
748 RenderPostText (writer);
751 protected virtual void RenderPreText (HtmlTextWriter writer)
755 protected virtual void RenderPostText (HtmlTextWriter writer)