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;
98 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
102 if (depth != -1) return depth;
104 TreeNode nod = parent;
105 while (nod != null) {
113 void ResetPathData ()
120 internal TreeView Tree {
125 value.SetSelectedNode (this, false);
126 else if (tree != null)
127 tree.SetSelectedNode (null, false);
131 nodes.SetTree (tree);
136 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
137 [DefaultValue (false)]
139 public bool DataBound {
140 get { return dataBound; }
143 [DefaultValue (null)]
145 public object DataItem {
147 if (!dataBound) throw new InvalidOperationException ("TreeNode is not data bound.");
152 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
155 public string DataPath {
157 if (!dataBound) throw new InvalidOperationException ("TreeNode is not data bound.");
162 [DefaultValue (false)]
163 public virtual bool Checked {
165 object o = ViewState ["Checked"];
166 if (o != null) return (bool)o;
170 ViewState ["Checked"] = value;
172 tree.NotifyCheckChanged (this);
176 [DefaultValue (null)]
177 [MergableProperty (false)]
179 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
180 public virtual TreeNodeCollection ChildNodes {
183 if (PopulateOnDemand && tree == null)
187 FillBoundChildren ();
189 nodes = new TreeNodeCollection (this);
191 if (IsTrackingViewState)
192 ((IStateManager)nodes).TrackViewState();
194 if (PopulateOnDemand && !Populated) {
203 [DefaultValue (false)]
204 public virtual bool Expanded {
206 object o = ViewState ["Expanded"];
207 if (o != null) return (bool)o;
211 ViewState ["Expanded"] = value;
213 tree.NotifyExpandedChanged (this);
219 public virtual string ImageToolTip {
221 object o = ViewState ["ImageToolTip"];
222 if (o != null) return (string)o;
224 TreeNodeBinding bin = GetBinding ();
226 if (bin.ImageToolTipField != "")
227 return (string) GetBoundPropertyValue (bin.ImageToolTipField);
228 return bin.ImageToolTip;
234 ViewState ["ImageToolTip"] = value;
240 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
241 public virtual string ImageUrl {
243 object o = ViewState ["ImageUrl"];
244 if (o != null) return (string)o;
246 TreeNodeBinding bin = GetBinding ();
248 if (bin.ImageUrlField != "")
249 return (string) GetBoundPropertyValue (bin.ImageUrlField);
256 ViewState ["ImageUrl"] = value;
262 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
263 public virtual string NavigateUrl {
265 object o = ViewState ["NavigateUrl"];
266 if (o != null) return (string)o;
268 TreeNodeBinding bin = GetBinding ();
270 if (bin.NavigateUrlField != "")
271 return (string) GetBoundPropertyValue (bin.NavigateUrlField);
272 return bin.NavigateUrl;
278 ViewState ["NavigateUrl"] = value;
282 [DefaultValue (false)]
283 public bool PopulateOnDemand {
285 object o = ViewState ["PopulateOnDemand"];
286 if (o != null) return (bool)o;
288 TreeNodeBinding bin = GetBinding ();
290 return bin.PopulateOnDemand;
295 ViewState ["PopulateOnDemand"] = value;
299 [DefaultValue (TreeNodeSelectAction.Select)]
300 public TreeNodeSelectAction SelectAction {
302 object o = ViewState ["SelectAction"];
303 if (o != null) return (TreeNodeSelectAction)o;
305 TreeNodeBinding bin = GetBinding ();
307 return bin.SelectAction;
309 return TreeNodeSelectAction.Select;
312 ViewState ["SelectAction"] = value;
316 [DefaultValue (false)]
317 public bool ShowCheckBox {
319 object o = ViewState ["ShowCheckBox"];
320 if (o != null) return (bool)o;
322 TreeNodeBinding bin = GetBinding ();
324 return bin.ShowCheckBox;
329 ViewState ["ShowCheckBox"] = value;
333 internal bool IsShowCheckBoxSet {
334 get { return ViewState ["ShowCheckBox"] != null; }
338 public virtual string Target {
340 object o = ViewState ["Target"];
341 if(o != null) return (string)o;
343 TreeNodeBinding bin = GetBinding ();
345 if (bin.TargetField != "")
346 return (string) GetBoundPropertyValue (bin.TargetField);
353 ViewState ["Target"] = value;
359 [WebSysDescription ("The display text of the tree node.")]
360 public virtual string Text {
362 object o = ViewState ["Text"];
363 if (o != null) return (string)o;
365 TreeNodeBinding bin = GetBinding ();
368 if (bin.TextField != "")
369 text = (string) GetBoundPropertyValue (bin.TextField);
370 else if (bin.Text != "")
373 text = GetDefaultBoundText ();
375 if (bin.FormatString.Length != 0)
376 text = string.Format (bin.FormatString, text);
379 return GetDefaultBoundText ();
384 ViewState ["Text"] = value;
390 public virtual string ToolTip {
392 object o = ViewState ["ToolTip"];
393 if(o != null) return (string)o;
395 TreeNodeBinding bin = GetBinding ();
397 if (bin.ToolTipField != "")
398 return (string) GetBoundPropertyValue (bin.ToolTipField);
405 ViewState ["ToolTip"] = value;
411 public virtual string Value {
413 object o = ViewState ["Value"];
414 if(o != null) return (string)o;
416 TreeNodeBinding bin = GetBinding ();
418 if (bin.ValueField != "")
419 return (string) GetBoundPropertyValue (bin.ValueField);
423 return GetDefaultBoundText ();
428 ViewState ["Value"] = value;
432 [DefaultValue (false)]
433 public virtual bool Selected {
439 if (!value && tree.SelectedNode == this)
440 tree.SetSelectedNode (null, false);
442 tree.SetSelectedNode (this, false);
445 SelectedFlag = value;
449 internal virtual bool SelectedFlag {
451 object o = ViewState ["Selected"];
452 if(o != null) return (bool)o;
456 ViewState ["Selected"] = value;
460 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
462 public TreeNode Parent {
463 get { return parent; }
466 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
468 public string ValuePath {
470 if (tree == null) return Value;
472 StringBuilder sb = new StringBuilder (Value);
473 TreeNode node = parent;
474 while (node != null) {
475 sb.Insert (0, tree.PathSeparator);
476 sb.Insert (0, node.Value);
479 return sb.ToString ();
484 get { return index; }
485 set { index = value; ResetPathData (); }
488 internal void SetParent (TreeNode node) {
493 internal string Path {
495 if (path != null) return path;
496 StringBuilder sb = new StringBuilder (index.ToString());
497 TreeNode node = parent;
498 while (node != null) {
500 sb.Insert (0, node.Index.ToString ());
503 path = sb.ToString ();
508 internal bool Populated {
510 object o = ViewState ["Populated"];
511 if (o != null) return (bool) o;
515 ViewState ["Populated"] = value;
519 internal bool HasChildData {
520 get { return nodes != null; }
523 protected virtual void Populate ()
525 tree.NotifyPopulateRequired (this);
528 public void Collapse ()
533 public void CollapseAll ()
535 SetExpandedRec (false, -1);
538 public void Expand ()
543 internal void Expand (int depth)
545 SetExpandedRec (true, depth);
548 public void ExpandAll ()
550 SetExpandedRec (true, -1);
553 void SetExpandedRec (bool expanded, int depth)
556 if (depth == 0) return;
558 foreach (TreeNode nod in ChildNodes)
559 nod.SetExpandedRec (expanded, depth - 1);
562 public void Select ()
567 public void ToggleExpandState ()
569 Expanded = !Expanded;
572 public void LoadViewState (object savedState)
574 if (savedState == null)
577 object[] states = (object[]) savedState;
578 ViewState.LoadViewState (states [0]);
580 if (tree != null && SelectedFlag)
581 tree.SetSelectedNode (this, true);
583 if (!PopulateOnDemand || Populated)
584 ((IStateManager)ChildNodes).LoadViewState (states [1]);
587 public object SaveViewState ()
589 object[] states = new object[2];
590 states[0] = ViewState.SaveViewState();
591 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
593 for (int i = 0; i < states.Length; i++) {
594 if (states [i] != null)
600 public void TrackViewState ()
604 ViewState.TrackViewState();
607 ((IStateManager)nodes).TrackViewState ();
610 public bool IsTrackingViewState
612 get { return marked; }
615 internal void SetDirty ()
617 ViewState.SetDirty (true);
620 public object Clone ()
622 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
623 foreach (DictionaryEntry e in ViewState)
624 nod.ViewState [(string)e.Key] = e.Value;
626 foreach (TreeNode c in ChildNodes)
627 nod.ChildNodes.Add ((TreeNode)c.Clone ());
632 internal void Bind (IHierarchyData hierarchyData)
634 this.hierarchyData = hierarchyData;
636 dataPath = hierarchyData.Path;
637 dataItem = hierarchyData.Item;
640 internal void SetDataItem (object item)
645 internal void SetDataPath (string path)
650 internal void SetDataBound (bool bound)
655 string GetDefaultBoundText ()
657 if (hierarchyData != null) return hierarchyData.ToString ();
658 else if (dataItem != null) return dataItem.ToString ();
659 else return string.Empty;
662 string GetDataItemType ()
664 if (hierarchyData != null) return hierarchyData.Type;
665 else if (dataItem != null) return dataItem.GetType().ToString ();
666 else return string.Empty;
669 internal bool IsParentNode {
670 get { return ChildNodes.Count > 0 && Parent != null; }
673 internal bool IsLeafNode {
674 get { return ChildNodes.Count == 0; }
677 internal bool IsRootNode {
678 get { return ChildNodes.Count > 0 && Parent == null; }
681 TreeNodeBinding GetBinding ()
683 if (tree == null) return null;
684 if (gotBinding) return binding;
685 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
690 object GetBoundPropertyValue (string name)
692 if (boundProperties == null) {
693 if (hierarchyData != null)
694 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
696 boundProperties = TypeDescriptor.GetProperties (dataItem);
699 PropertyDescriptor prop = boundProperties.Find (name, true);
701 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
703 if (hierarchyData != null)
704 return prop.GetValue (hierarchyData);
706 return prop.GetValue (dataItem);
709 void FillBoundChildren ()
711 nodes = new TreeNodeCollection (this);
712 if (hierarchyData == null || !hierarchyData.HasChildren) return;
713 if (tree.MaxDataBindDepth != -1 && Depth >= tree.MaxDataBindDepth) return;
715 IHierarchicalEnumerable e = hierarchyData.GetChildren ();
716 foreach (object obj in e) {
717 IHierarchyData hdata = e.GetHierarchyData (obj);
718 TreeNode node = tree != null ? tree.CreateNode () : new TreeNode ();
724 internal void BeginRenderText (HtmlTextWriter writer)
726 RenderPreText (writer);
729 internal void EndRenderText (HtmlTextWriter writer)
731 RenderPostText (writer);
734 protected virtual void RenderPreText (HtmlTextWriter writer)
738 protected virtual void RenderPostText (HtmlTextWriter writer)