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.");
168 [DefaultValue (false)]
169 public bool Checked {
171 object o = ViewState ["Checked"];
172 if (o != null) return (bool)o;
176 ViewState ["Checked"] = value;
178 tree.NotifyCheckChanged (this);
182 [DefaultValue (null)]
183 [MergableProperty (false)]
185 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
186 public TreeNodeCollection ChildNodes {
189 if (PopulateOnDemand && tree == null)
193 FillBoundChildren ();
195 nodes = new TreeNodeCollection (this);
197 if (IsTrackingViewState)
198 ((IStateManager)nodes).TrackViewState();
200 if (PopulateOnDemand && !Populated) {
209 [DefaultValue (null)]
210 public bool? Expanded {
212 object o = ViewState ["Expanded"];
213 if (o != null) return (bool)o;
217 ViewState ["Expanded"] = value;
219 tree.NotifyExpandedChanged (this);
225 public string ImageToolTip {
227 object o = ViewState ["ImageToolTip"];
228 if (o != null) return (string)o;
230 TreeNodeBinding bin = GetBinding ();
232 if (bin.ImageToolTipField != "")
233 return (string) GetBoundPropertyValue (bin.ImageToolTipField);
234 return bin.ImageToolTip;
240 ViewState ["ImageToolTip"] = value;
246 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
247 public string ImageUrl {
249 object o = ViewState ["ImageUrl"];
250 if (o != null) return (string)o;
252 TreeNodeBinding bin = GetBinding ();
254 if (bin.ImageUrlField != "")
255 return (string) GetBoundPropertyValue (bin.ImageUrlField);
262 ViewState ["ImageUrl"] = value;
268 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
269 public string NavigateUrl {
271 object o = ViewState ["NavigateUrl"];
272 if (o != null) return (string)o;
274 TreeNodeBinding bin = GetBinding ();
276 if (bin.NavigateUrlField != "")
277 return (string) GetBoundPropertyValue (bin.NavigateUrlField);
278 return bin.NavigateUrl;
284 ViewState ["NavigateUrl"] = value;
288 [DefaultValue (false)]
289 public bool PopulateOnDemand {
291 object o = ViewState ["PopulateOnDemand"];
292 if (o != null) return (bool)o;
294 TreeNodeBinding bin = GetBinding ();
296 return bin.PopulateOnDemand;
301 ViewState ["PopulateOnDemand"] = value;
305 [DefaultValue (TreeNodeSelectAction.Select)]
306 public TreeNodeSelectAction SelectAction {
308 object o = ViewState ["SelectAction"];
309 if (o != null) return (TreeNodeSelectAction)o;
311 TreeNodeBinding bin = GetBinding ();
313 return bin.SelectAction;
315 return TreeNodeSelectAction.Select;
318 ViewState ["SelectAction"] = value;
322 [DefaultValue (null)]
323 public bool? ShowCheckBox {
325 object o = ViewState ["ShowCheckBox"];
326 if (o != null) return (bool)o;
328 TreeNodeBinding bin = GetBinding ();
330 return bin.ShowCheckBox;
335 ViewState ["ShowCheckBox"] = value;
339 internal bool IsShowCheckBoxSet {
340 get { return ViewState ["ShowCheckBox"] != null; }
344 public string Target {
346 object o = ViewState ["Target"];
347 if(o != null) return (string)o;
349 TreeNodeBinding bin = GetBinding ();
351 if (bin.TargetField != "")
352 return (string) GetBoundPropertyValue (bin.TargetField);
359 ViewState ["Target"] = value;
365 [WebSysDescription ("The display text of the tree node.")]
368 object o = ViewState ["Text"];
369 if (o != null) return (string)o;
371 TreeNodeBinding bin = GetBinding ();
374 if (bin.TextField != "")
375 text = (string) GetBoundPropertyValue (bin.TextField);
376 else if (bin.Text != "")
379 text = GetDefaultBoundText ();
381 if (bin.FormatString.Length != 0)
382 text = string.Format (bin.FormatString, text);
385 return GetDefaultBoundText ();
390 ViewState ["Text"] = value;
396 public string ToolTip {
398 object o = ViewState ["ToolTip"];
399 if(o != null) return (string)o;
401 TreeNodeBinding bin = GetBinding ();
403 if (bin.ToolTipField != "")
404 return (string) GetBoundPropertyValue (bin.ToolTipField);
411 ViewState ["ToolTip"] = value;
417 public string Value {
419 object o = ViewState ["Value"];
420 if(o != null) return (string)o;
422 TreeNodeBinding bin = GetBinding ();
424 if (bin.ValueField != "")
425 return (string) GetBoundPropertyValue (bin.ValueField);
429 return GetDefaultBoundText ();
434 ViewState ["Value"] = value;
438 [DefaultValue (false)]
439 public bool Selected {
445 if (!value && tree.SelectedNode == this)
446 tree.SetSelectedNode (null, false);
448 tree.SetSelectedNode (this, false);
451 SelectedFlag = value;
455 internal virtual bool SelectedFlag {
457 object o = ViewState ["Selected"];
458 if(o != null) return (bool)o;
462 ViewState ["Selected"] = value;
466 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
468 public TreeNode Parent {
469 get { return parent; }
472 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
474 public string ValuePath {
476 if (tree == null) return Value;
478 StringBuilder sb = new StringBuilder (Value);
479 TreeNode node = parent;
480 while (node != null) {
481 sb.Insert (0, tree.PathSeparator);
482 sb.Insert (0, node.Value);
485 return sb.ToString ();
490 get { return index; }
491 set { index = value; ResetPathData (); }
494 internal void SetParent (TreeNode node) {
499 internal string Path {
501 if (path != null) return path;
502 StringBuilder sb = new StringBuilder (index.ToString());
503 TreeNode node = parent;
504 while (node != null) {
506 sb.Insert (0, node.Index.ToString ());
509 path = sb.ToString ();
514 internal bool Populated {
516 object o = ViewState ["Populated"];
517 if (o != null) return (bool) o;
521 ViewState ["Populated"] = value;
525 internal bool HasChildData {
526 get { return nodes != null; }
529 internal void Populate ()
531 tree.NotifyPopulateRequired (this);
534 public void Collapse ()
539 public void CollapseAll ()
541 SetExpandedRec (false, -1);
544 public void Expand ()
549 internal void Expand (int depth)
551 SetExpandedRec (true, depth);
554 public void ExpandAll ()
556 SetExpandedRec (true, -1);
559 void SetExpandedRec (bool expanded, int depth)
562 if (depth == 0) return;
564 foreach (TreeNode nod in ChildNodes)
565 nod.SetExpandedRec (expanded, depth - 1);
568 public void Select ()
573 public void ToggleExpandState ()
575 Expanded = !Expanded;
578 void IStateManager.LoadViewState (object savedState)
580 LoadViewState (savedState);
583 protected virtual void LoadViewState (object savedState)
585 if (savedState == null)
588 object[] states = (object[]) savedState;
589 ViewState.LoadViewState (states [0]);
591 if (tree != null && SelectedFlag)
592 tree.SetSelectedNode (this, true);
594 if (!PopulateOnDemand || Populated)
595 ((IStateManager)ChildNodes).LoadViewState (states [1]);
598 object IStateManager.SaveViewState ()
600 return SaveViewState ();
603 protected virtual object SaveViewState ()
605 object[] states = new object[2];
606 states[0] = ViewState.SaveViewState();
607 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
609 for (int i = 0; i < states.Length; i++) {
610 if (states [i] != null)
616 void IStateManager.TrackViewState ()
621 protected void TrackViewState ()
625 ViewState.TrackViewState();
628 ((IStateManager)nodes).TrackViewState ();
631 bool IStateManager.IsTrackingViewState {
632 get { return IsTrackingViewState; }
635 protected bool IsTrackingViewState
637 get { return marked; }
640 internal void SetDirty ()
642 ViewState.SetDirty (true);
645 public virtual object Clone ()
647 TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
648 foreach (DictionaryEntry e in ViewState)
649 nod.ViewState [(string)e.Key] = e.Value;
651 foreach (TreeNode c in ChildNodes)
652 nod.ChildNodes.Add ((TreeNode)c.Clone ());
657 internal void Bind (IHierarchyData hierarchyData)
659 this.hierarchyData = hierarchyData;
661 dataPath = hierarchyData.Path;
662 dataItem = hierarchyData.Item;
665 internal void SetDataItem (object item)
670 internal void SetDataPath (string path)
675 internal void SetDataBound (bool bound)
680 string GetDefaultBoundText ()
682 if (hierarchyData != null) return hierarchyData.ToString ();
683 else if (dataItem != null) return dataItem.ToString ();
684 else return string.Empty;
687 string GetDataItemType ()
689 if (hierarchyData != null) return hierarchyData.Type;
690 else if (dataItem != null) return dataItem.GetType().ToString ();
691 else return string.Empty;
694 internal bool IsParentNode {
695 get { return ChildNodes.Count > 0 && Parent != null; }
698 internal bool IsLeafNode {
699 get { return ChildNodes.Count == 0; }
702 internal bool IsRootNode {
703 get { return ChildNodes.Count > 0 && Parent == null; }
706 TreeNodeBinding GetBinding ()
708 if (tree == null) return null;
709 if (gotBinding) return binding;
710 binding = tree.FindBindingForNode (GetDataItemType (), Depth);
715 object GetBoundPropertyValue (string name)
717 if (boundProperties == null) {
718 if (hierarchyData != null)
719 boundProperties = TypeDescriptor.GetProperties (hierarchyData);
721 boundProperties = TypeDescriptor.GetProperties (dataItem);
724 PropertyDescriptor prop = boundProperties.Find (name, true);
726 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
728 if (hierarchyData != null)
729 return prop.GetValue (hierarchyData);
731 return prop.GetValue (dataItem);
734 void FillBoundChildren ()
736 nodes = new TreeNodeCollection (this);
737 if (hierarchyData == null || !hierarchyData.HasChildren) return;
738 if (tree.MaxDataBindDepth != -1 && Depth >= tree.MaxDataBindDepth) return;
740 IHierarchicalEnumerable e = hierarchyData.GetChildren ();
741 foreach (object obj in e) {
742 IHierarchyData hdata = e.GetHierarchyData (obj);
743 TreeNode node = tree != null ? tree.CreateNode () : new TreeNode ();
749 internal void BeginRenderText (HtmlTextWriter writer)
751 RenderPreText (writer);
754 internal void EndRenderText (HtmlTextWriter writer)
756 RenderPostText (writer);
759 protected virtual void RenderPreText (HtmlTextWriter writer)
763 protected virtual void RenderPostText (HtmlTextWriter writer)