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;
53 IHierarchyData hierarchyData;
55 TreeNodeBinding binding;
56 PropertyDescriptorCollection boundProperties;
58 internal TreeNode (TreeView tree)
67 public TreeNode (string text)
72 public TreeNode (string text, string value)
78 public TreeNode (string text, string value, string imageUrl)
85 public TreeNode (string text, string value, string imageUrl, string navigateUrl, string target)
90 NavigateUrl = navigateUrl;
94 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
98 if (depth != -1) return depth;
100 TreeNode nod = parent;
101 while (nod != null) {
109 void ResetPathData ()
116 internal TreeView Tree {
121 value.SetSelectedNode (this);
122 else if (tree != null)
123 tree.SetSelectedNode (null);
127 nodes.SetTree (tree);
132 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
133 [DefaultValue (false)]
135 public bool DataBound {
136 get { return hierarchyData != null; }
139 [DefaultValue (null)]
141 public object DataItem {
143 if (hierarchyData == null) throw new InvalidOperationException ("TreeNode is not data bound.");
144 return hierarchyData.Item;
148 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
151 public string DataPath {
153 if (hierarchyData == null) throw new InvalidOperationException ("TreeNode is not data bound.");
154 return hierarchyData.Path;
158 [DefaultValue (false)]
159 public virtual bool Checked {
161 object o = ViewState ["Checked"];
162 if (o != null) return (bool)o;
166 ViewState ["Checked"] = value;
168 tree.NotifyCheckChanged (this);
172 [DefaultValue (null)]
173 [MergableProperty (false)]
175 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
176 public virtual TreeNodeCollection ChildNodes {
179 if (PopulateOnDemand && tree == null)
183 FillBoundChildren ();
185 nodes = new TreeNodeCollection (this);
187 if (IsTrackingViewState)
188 ((IStateManager)nodes).TrackViewState();
190 if (PopulateOnDemand && !Populated) {
199 [DefaultValue (false)]
200 public virtual bool Expanded {
202 object o = ViewState ["Expanded"];
203 if (o != null) return (bool)o;
207 ViewState ["Expanded"] = value;
209 tree.NotifyExpandedChanged (this);
215 public virtual string ImageToolTip {
217 object o = ViewState ["ImageToolTip"];
218 if (o != null) return (string)o;
220 TreeNodeBinding bin = GetBinding ();
222 if (bin.ImageToolTipField != "")
223 return (string) GetBoundPropertyValue (bin.ImageToolTipField);
224 return bin.ImageToolTip;
230 ViewState ["ImageToolTip"] = value;
236 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
237 public virtual string ImageUrl {
239 object o = ViewState ["ImageUrl"];
240 if (o != null) return (string)o;
242 TreeNodeBinding bin = GetBinding ();
244 if (bin.ImageUrlField != "")
245 return (string) GetBoundPropertyValue (bin.ImageUrlField);
252 ViewState ["ImageUrl"] = value;
258 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
259 public virtual string NavigateUrl {
261 object o = ViewState ["NavigateUrl"];
262 if (o != null) return (string)o;
264 TreeNodeBinding bin = GetBinding ();
266 if (bin.NavigateUrlField != "")
267 return (string) GetBoundPropertyValue (bin.NavigateUrlField);
268 return bin.NavigateUrl;
274 ViewState ["NavigateUrl"] = value;
278 [DefaultValue (false)]
279 public bool PopulateOnDemand {
281 object o = ViewState ["PopulateOnDemand"];
282 if (o != null) return (bool)o;
284 TreeNodeBinding bin = GetBinding ();
286 return bin.PopulateOnDemand;
291 ViewState ["PopulateOnDemand"] = value;
295 [DefaultValue (TreeNodeSelectAction.Select)]
296 public TreeNodeSelectAction SelectAction {
298 object o = ViewState ["SelectAction"];
299 if (o != null) return (TreeNodeSelectAction)o;
301 TreeNodeBinding bin = GetBinding ();
303 return bin.SelectAction;
305 return TreeNodeSelectAction.Select;
308 ViewState ["SelectAction"] = value;
312 [DefaultValue (false)]
313 public bool ShowCheckBox {
315 object o = ViewState ["ShowCheckBox"];
316 if (o != null) return (bool)o;
318 TreeNodeBinding bin = GetBinding ();
320 return bin.ShowCheckBox;
325 ViewState ["ShowCheckBox"] = value;
329 internal bool IsShowCheckBoxSet {
330 get { return ViewState ["ShowCheckBox"] != null; }
334 public virtual string Target {
336 object o = ViewState ["Target"];
337 if(o != null) return (string)o;
339 TreeNodeBinding bin = GetBinding ();
341 if (bin.TargetField != "")
342 return (string) GetBoundPropertyValue (bin.TargetField);
349 ViewState ["Target"] = value;
355 [WebSysDescription ("The display text of the tree node.")]
356 public virtual string Text {
358 object o = ViewState ["Text"];
359 if (o != null) return (string)o;
361 TreeNodeBinding bin = GetBinding ();
364 if (bin.TextField != "")
365 text = (string) GetBoundPropertyValue (bin.TextField);
366 else if (bin.Text != "")
369 text = hierarchyData.ToString ();
371 if (bin.FormatString.Length != 0)
372 text = string.Format (bin.FormatString, text);
375 return hierarchyData.ToString ();
380 ViewState ["Text"] = value;
386 public virtual string ToolTip {
388 object o = ViewState ["ToolTip"];
389 if(o != null) return (string)o;
391 TreeNodeBinding bin = GetBinding ();
393 if (bin.ToolTipField != "")
394 return (string) GetBoundPropertyValue (bin.ToolTipField);
401 ViewState ["ToolTip"] = value;
407 public virtual string Value {
409 object o = ViewState ["Value"];
410 if(o != null) return (string)o;
412 TreeNodeBinding bin = GetBinding ();
414 if (bin.ValueField != "")
415 return (string) GetBoundPropertyValue (bin.ValueField);
419 return hierarchyData.ToString ();
424 ViewState ["Value"] = value;
428 [DefaultValue (false)]
429 public virtual bool Selected {
435 if (!value && tree.SelectedNode == this)
436 tree.SetSelectedNode (null);
438 tree.SetSelectedNode (this);
441 SelectedFlag = value;
445 internal virtual bool SelectedFlag {
447 object o = ViewState ["Selected"];
448 if(o != null) return (bool)o;
452 ViewState ["Selected"] = value;
456 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
458 public TreeNode Parent {
459 get { return parent; }
462 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
464 public string ValuePath {
466 if (tree == null) return Value;
468 StringBuilder sb = new StringBuilder (Value);
469 TreeNode node = parent;
470 while (node != null) {
471 sb.Insert (0, tree.PathSeparator);
472 sb.Insert (0, node.Value);
475 return sb.ToString ();
480 get { return index; }
481 set { index = value; ResetPathData (); }
484 internal void SetParent (TreeNode node) {
489 internal string Path {
491 if (path != null) return path;
492 StringBuilder sb = new StringBuilder (index.ToString());
493 TreeNode node = parent;
494 while (node != null) {
496 sb.Insert (0, node.Index.ToString ());
499 path = sb.ToString ();
504 internal bool Populated {
506 object o = ViewState ["Populated"];
507 if (o != null) return (bool) o;
511 ViewState ["Populated"] = value;
515 internal bool HasChildData {
516 get { return nodes != null; }
519 protected virtual void Populate ()
521 tree.NotifyPopulateRequired (this);
524 public void Collapse ()
529 public void CollapseAll ()
531 SetExpandedRec (false, -1);
534 public void Expand ()
539 internal void Expand (int depth)
541 SetExpandedRec (true, depth);
544 public void ExpandAll ()
546 SetExpandedRec (true, -1);
549 void SetExpandedRec (bool expanded, int depth)
552 if (depth == 0) return;
554 foreach (TreeNode nod in ChildNodes)
555 nod.SetExpandedRec (expanded, depth - 1);
558 public void Select ()
563 public void ToggleExpandState ()
565 Expanded = !Expanded;
568 public void LoadViewState (object savedState)
570 if (savedState == null)
573 object[] states = (object[]) savedState;
574 ViewState.LoadViewState (states [0]);
576 if (tree != null && SelectedFlag)
577 tree.SetSelectedNode (this);
579 if (!PopulateOnDemand || Populated)
580 ((IStateManager)ChildNodes).LoadViewState (states [1]);
583 public object SaveViewState ()
585 object[] states = new object[2];
586 states[0] = ViewState.SaveViewState();
587 states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
589 for (int i = 0; i < states.Length; i++) {
590 if (states [i] != null)
596 public void TrackViewState ()
600 ViewState.TrackViewState();
603 ((IStateManager)nodes).TrackViewState ();
606 public bool IsTrackingViewState
608 get { return marked; }
611 internal void SetDirty ()
613 ViewState.SetDirty ();
616 public object Clone ()
618 TreeNode nod = new TreeNode ();
619 foreach (DictionaryEntry e in ViewState)
620 nod.ViewState [(string)e.Key] = e.Value;
622 foreach (TreeNode c in ChildNodes)
623 nod.ChildNodes.Add ((TreeNode)c.Clone ());
628 internal void Bind (IHierarchyData hierarchyData)
630 this.hierarchyData = hierarchyData;
633 internal bool IsParentNode {
634 get { return ChildNodes.Count > 0 && Parent != null; }
637 internal bool IsLeafNode {
638 get { return ChildNodes.Count == 0; }
641 internal bool IsRootNode {
642 get { return ChildNodes.Count > 0 && Parent == null; }
645 TreeNodeBinding GetBinding ()
647 if (tree == null) return null;
648 if (gotBinding) return binding;
649 binding = tree.FindBindingForNode (hierarchyData.Type, Depth);
654 object GetBoundPropertyValue (string name)
656 if (boundProperties == null) {
657 ICustomTypeDescriptor desc = hierarchyData as ICustomTypeDescriptor;
659 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
660 boundProperties = desc.GetProperties ();
663 PropertyDescriptor prop = boundProperties.Find (name, true);
665 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
666 return prop.GetValue (hierarchyData);
669 void FillBoundChildren ()
671 nodes = new TreeNodeCollection (this);
672 if (!hierarchyData.HasChildren) return;
673 if (tree.MaxDataBindDepth != -1 && Depth >= tree.MaxDataBindDepth) return;
675 IHierarchicalEnumerable e = hierarchyData.GetChildren ();
676 foreach (object obj in e) {
677 IHierarchyData hdata = e.GetHierarchyData (obj);
678 TreeNode node = new TreeNode ();