Merge pull request #2916 from ludovic-henry/fix-40306
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / TreeNode.cs
index e5b5f5579779d571f1cba237edfc29bde3b8eadf..73c8d5fc401e4771f6d11c21fd86b140f15d66a0 100644 (file)
@@ -28,7 +28,6 @@
 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
 //
 
-#if NET_2_0
 
 using System;
 using System.Collections;
@@ -50,10 +49,14 @@ namespace System.Web.UI.WebControls
                string path;
                int depth = -1;
                
+               object dataItem;
                IHierarchyData hierarchyData;
+
                bool gotBinding;
                TreeNodeBinding binding;
                PropertyDescriptorCollection boundProperties;
+               bool populating;
+               bool hadChildrenBeforePopulating;
                
                internal TreeNode (TreeView tree)
                {
@@ -91,6 +94,12 @@ namespace System.Web.UI.WebControls
                        Target = target;
                }
                
+               [MonoTODO ("Not implemented")]
+               protected TreeNode (TreeView owner, bool isRoot)
+               {
+                       throw new NotImplementedException ();
+               }
+
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [Browsable (false)]
                public int Depth {
@@ -111,6 +120,10 @@ namespace System.Web.UI.WebControls
                        path = null;
                        depth = -1;
                        gotBinding = false;
+                       if (nodes != null) {
+                               foreach (TreeNode node in nodes)
+                                       node.ResetPathData ();
+                       }
                }
                
                internal TreeView Tree {
@@ -119,13 +132,13 @@ namespace System.Web.UI.WebControls
                                if (SelectedFlag) {
                                        if (value != null)
                                                value.SetSelectedNode (this, false);
-                                       else if (tree != null)
-                                               tree.SetSelectedNode (null, false);
                                }
                                tree = value;
                                if (nodes != null)
                                        nodes.SetTree (tree);
                                ResetPathData ();
+                               if (PopulateOnDemand && !Populated && Expanded.HasValue && Expanded.Value)
+                                       Populate ();
                        }
                }
                
@@ -133,30 +146,26 @@ namespace System.Web.UI.WebControls
                [DefaultValue (false)]
                [Browsable (false)]
                public bool DataBound {
-                       get { return hierarchyData != null; }
+                       get { return ViewState ["DataBound"] == null ? false : (bool) ViewState ["DataBound"]; }
+                       private set { ViewState ["DataBound"] = value; }
                }
                
                [DefaultValue (null)]
                [Browsable (false)]
                public object DataItem {
-                       get {
-                               if (hierarchyData == null) throw new InvalidOperationException ("TreeNode is not data bound.");
-                               return hierarchyData.Item;
-                       }
+                       get { return dataItem; }
                }
                
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [DefaultValue ("")]
                [Browsable (false)]
                public string DataPath {
-                       get {
-                               if (hierarchyData == null) throw new InvalidOperationException ("TreeNode is not data bound.");
-                               return hierarchyData.Path;
-                       }
+                       get { return ViewState ["DataPath"] == null ? String.Empty : (String) ViewState ["DataPath"]; }
+                       private set { ViewState ["DataPath"] = value; }
                }
                
                [DefaultValue (false)]
-               public virtual bool Checked {
+               public bool Checked {
                        get {
                                object o = ViewState ["Checked"];
                                if (o != null) return (bool)o;
@@ -173,122 +182,98 @@ namespace System.Web.UI.WebControls
                [MergableProperty (false)]
                [Browsable (false)]
                [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
-               public virtual TreeNodeCollection ChildNodes {
+               public TreeNodeCollection ChildNodes {
                        get {
                                if (nodes == null) {
-                                       if (PopulateOnDemand && tree == null)
-                                               return null;
-
-                                       if (DataBound)
-                                               FillBoundChildren ();
-                                       else
-                                               nodes = new TreeNodeCollection (this);
+                                       nodes = new TreeNodeCollection (this);
                                                
                                        if (IsTrackingViewState)
                                                ((IStateManager)nodes).TrackViewState();
-                                       
-                                       if (PopulateOnDemand && !Populated) {
-                                               Populated = true;
-                                               Populate ();
-                                       }
                                }
                                return nodes;
                        }
                }
                
-               [DefaultValue (false)]
-               public virtual bool Expanded {
+               [DefaultValue (null)]
+               public bool? Expanded {
                        get {
                                object o = ViewState ["Expanded"];
-                               if (o != null) return (bool)o;
-                               return false;
+                               return (bool?)o;
                        }
                        set {
+                               bool? current = (bool?) ViewState ["Expanded"];
+                               if (current == value)
+                                       return;
                                ViewState ["Expanded"] = value;
                                if (tree != null)
                                        tree.NotifyExpandedChanged (this);
+                               if (PopulateOnDemand && !Populated && value.HasValue && value.Value)
+                                       Populate ();
                        }
                }
 
                [Localizable (true)]
                [DefaultValue ("")]
-               public virtual string ImageToolTip {
+               public string ImageToolTip {
                        get {
                                object o = ViewState ["ImageToolTip"];
-                               if (o != null) return (string)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null) {
-                                               if (bin.ImageToolTipField != "")
-                                                       return (string) GetBoundPropertyValue (bin.ImageToolTipField);
-                                               return bin.ImageToolTip;
-                                       }
-                               }
-                               return "";
-                       }
-                       set {
-                               ViewState ["ImageToolTip"] = value;
+                               if (o != null)
+                                       return (string)o;
+                               return String.Empty;
                        }
+                       set { ViewState ["ImageToolTip"] = value; }
                }
                
                [DefaultValue ("")]
                [UrlProperty]
                [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
-               public virtual string ImageUrl {
+               public string ImageUrl {
                        get {
                                object o = ViewState ["ImageUrl"];
-                               if (o != null) return (string)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null) {
-                                               if (bin.ImageUrlField != "")
-                                                       return (string) GetBoundPropertyValue (bin.ImageUrlField);
-                                               return bin.ImageUrl;
-                                       }
-                               }
-                               return "";
-                       }
-                       set {
-                               ViewState ["ImageUrl"] = value;
+                               if (o != null)
+                                       return (string)o;
+                               return String.Empty;
                        }
+                       set { ViewState ["ImageUrl"] = value; }
                }
 
                [DefaultValue ("")]
                [UrlProperty]
                [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
-               public virtual string NavigateUrl {
+               public string NavigateUrl {
                        get {
                                object o = ViewState ["NavigateUrl"];
-                               if (o != null) return (string)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null) {
-                                               if (bin.NavigateUrlField != "")
-                                                       return (string) GetBoundPropertyValue (bin.NavigateUrlField);
-                                               return bin.NavigateUrl;
-                                       }
-                               }
-                               return "";
+                               if (o != null)
+                                       return (string)o;
+                               return String.Empty;
                        }
+                       set { ViewState ["NavigateUrl"] = value; }
+               }
+
+               internal bool HadChildrenBeforePopulating {
+                       get { return hadChildrenBeforePopulating; }
                        set {
-                               ViewState ["NavigateUrl"] = value;
+                               if (populating)
+                                       return;
+
+                               hadChildrenBeforePopulating = value;
                        }
                }
-
+               
                [DefaultValue (false)]
                public bool PopulateOnDemand {
                        get {
                                object o = ViewState ["PopulateOnDemand"];
-                               if (o != null) return (bool)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null)
-                                               return bin.PopulateOnDemand;
-                               }
+                               if (o != null)
+                                       return (bool)o;
                                return false;
                        }
                        set {
                                ViewState ["PopulateOnDemand"] = value;
+                               if (value && nodes != null && nodes.Count > 0)
+                                       HadChildrenBeforePopulating = true;
+                               else
+                                       HadChildrenBeforePopulating = false;
                        }
                }
 
@@ -296,161 +281,109 @@ namespace System.Web.UI.WebControls
                public TreeNodeSelectAction SelectAction {
                        get {
                                object o = ViewState ["SelectAction"];
-                               if (o != null) return (TreeNodeSelectAction)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null)
-                                               return bin.SelectAction;
-                               }
+                               if (o != null)
+                                       return (TreeNodeSelectAction)o;
                                return TreeNodeSelectAction.Select;
                        }
-                       set {
-                               ViewState ["SelectAction"] = value;
-                       }
+                       set { ViewState ["SelectAction"] = value; }
                }
 
-               [DefaultValue (false)]
-               public bool ShowCheckBox {
+               [DefaultValue (null)]
+               public bool? ShowCheckBox {
                        get {
                                object o = ViewState ["ShowCheckBox"];
-                               if (o != null) return (bool)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null)
-                                               return bin.ShowCheckBox;
-                               }
-                               return false;
+                               return (bool?)o;
                        }
-                       set {
-                               ViewState ["ShowCheckBox"] = value;
+                       set { ViewState ["ShowCheckBox"] = value; }
+               }
+
+               internal bool ShowCheckBoxInternal {
+                       get {
+                               if (ShowCheckBox.HasValue)
+                                       return ShowCheckBox.Value;
+                               else
+                                       return (Tree.ShowCheckBoxes == TreeNodeTypes.All) ||
+                                                ((Tree.ShowCheckBoxes & TreeNodeTypes.Leaf) > 0 && IsLeafNode) ||
+                                                ((Tree.ShowCheckBoxes & TreeNodeTypes.Parent) > 0 && IsParentNode && Parent != null) ||
+                                                ((Tree.ShowCheckBoxes & TreeNodeTypes.Root) > 0 && Parent == null && ChildNodes.Count > 0);
                        }
                }
                
-               internal bool IsShowCheckBoxSet {
-                       get { return ViewState ["ShowCheckBox"] != null; }
-               }
-
                [DefaultValue ("")]
-               public virtual string Target {
+               public string Target {
                        get {
                                object o = ViewState ["Target"];
-                               if(o != null) return (string)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null) {
-                                               if (bin.TargetField != "")
-                                                       return (string) GetBoundPropertyValue (bin.TargetField);
-                                               return bin.Target;
-                                       }
-                               }
-                               return "";
-                       }
-                       set {
-                               ViewState ["Target"] = value;
+                               if(o != null)
+                                       return (string)o;
+                               return String.Empty;
                        }
+                       set { ViewState ["Target"] = value; }
                }
 
                [Localizable (true)]
                [DefaultValue ("")]
                [WebSysDescription ("The display text of the tree node.")]
-               public virtual string Text {
+               public string Text {
                        get {
                                object o = ViewState ["Text"];
-                               if (o != null) return (string)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null) {
-                                               string text;
-                                               if (bin.TextField != "")
-                                                       text = (string) GetBoundPropertyValue (bin.TextField);
-                                               else if (bin.Text != "")
-                                                       text = bin.Text;
-                                               else
-                                                       text = hierarchyData.ToString ();
-                                                       
-                                               if (bin.FormatString.Length != 0)
-                                                       text = string.Format (bin.FormatString, text);
-                                               return text;
-                                       }
-                                       return hierarchyData.ToString ();
-                               }
-                               return "";
-                       }
-                       set {
-                               ViewState ["Text"] = value;
+                               if (o == null)
+                                       o = ViewState ["Value"];
+                               if (o != null)
+                                       return (string)o;
+                               return String.Empty;
                        }
+                       set { ViewState ["Text"] = value; }
                }
 
                [Localizable (true)]
                [DefaultValue ("")]
-               public virtual string ToolTip {
+               public string ToolTip {
                        get {
                                object o = ViewState ["ToolTip"];
-                               if(o != null) return (string)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null) {
-                                               if (bin.ToolTipField != "")
-                                                       return (string) GetBoundPropertyValue (bin.ToolTipField);
-                                               return bin.ToolTip;
-                                       }
-                               }
-                               return "";
-                       }
-                       set {
-                               ViewState ["ToolTip"] = value;
+                               if(o != null)
+                                       return (string)o;
+                               return String.Empty;
                        }
+                       set { ViewState ["ToolTip"] = value; }
                }
 
                [Localizable (true)]
                [DefaultValue ("")]
-               public virtual string Value {
+               public string Value {
                        get {
                                object o = ViewState ["Value"];
-                               if(o != null) return (string)o;
-                               if (DataBound) {
-                                       TreeNodeBinding bin = GetBinding ();
-                                       if (bin != null) {
-                                               if (bin.ValueField != "")
-                                                       return (string) GetBoundPropertyValue (bin.ValueField);
-                                               if (bin.Value != "")
-                                                       return bin.Value;
-                                       }
-                                       return hierarchyData.ToString ();
-                               }
-                               return "";
-                       }
-                       set {
-                               ViewState ["Value"] = value;
+                               if (o == null)
+                                       o = ViewState ["Text"];
+                               if(o != null)
+                                       return (string)o;
+                               return String.Empty;
                        }
+                       set { ViewState ["Value"] = value; }
                }
                
                [DefaultValue (false)]
-               public virtual bool Selected {
-                       get {
-                               return SelectedFlag;
-                       }
+               public bool Selected {
+                       get { return SelectedFlag; }
                        set {
+                               SelectedFlag = value;
+                               
                                if (tree != null) {
                                        if (!value && tree.SelectedNode == this)
                                                tree.SetSelectedNode (null, false);
                                        else if (value)
                                                tree.SetSelectedNode (this, false);
                                }
-                               else
-                                       SelectedFlag = value;
                        }
                }
                
                internal virtual bool SelectedFlag {
                        get {
                                object o = ViewState ["Selected"];
-                               if(o != null) return (bool)o;
+                               if(o != null)
+                                       return (bool)o;
                                return false;
                        }
-                       set {
-                               ViewState ["Selected"] = value;
-                       }
+                       set { ViewState ["Selected"] = value; }
                }
                
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
@@ -481,14 +414,16 @@ namespace System.Web.UI.WebControls
                        set { index = value; ResetPathData (); }
                }
                
-               internal void SetParent (TreeNode node) {
+               internal void SetParent (TreeNode node)
+               {
                        parent = node;
                        ResetPathData ();
                }
                
                internal string Path {
                        get {
-                               if (path != null) return path;
+                               if (path != null)
+                                       return path;
                                StringBuilder sb = new StringBuilder (index.ToString());
                                TreeNode node = parent;
                                while (node != null) {
@@ -504,21 +439,26 @@ namespace System.Web.UI.WebControls
                internal bool Populated {
                        get {
                                object o = ViewState ["Populated"];
-                               if (o != null) return (bool) o;
+                               if (o != null)
+                                       return (bool) o;
                                return false;
                        }
-                       set {
-                               ViewState ["Populated"] = value;
-                       }
+                       set { ViewState ["Populated"] = value; }
                }
 
                internal bool HasChildData {
                        get { return nodes != null; }
                }
                
-               protected virtual void Populate ()
+               internal void Populate ()
                {
+                       if (tree == null)
+                               return;
+
+                       populating = true;
                        tree.NotifyPopulateRequired (this);
+                       populating = false;
+                       Populated = true;
                }
                
                public void Collapse ()
@@ -549,7 +489,8 @@ namespace System.Web.UI.WebControls
                void SetExpandedRec (bool expanded, int depth)
                {
                        Expanded = expanded;
-                       if (depth == 0) return;
+                       if (depth == 0)
+                               return;
                        
                        foreach (TreeNode nod in ChildNodes)
                                nod.SetExpandedRec (expanded, depth - 1);
@@ -562,10 +503,15 @@ namespace System.Web.UI.WebControls
                
                public void ToggleExpandState ()
                {
-                       Expanded = !Expanded;
+                       Expanded = !Expanded.GetValueOrDefault(false);
+               }
+
+               void IStateManager.LoadViewState (object savedState)
+               {
+                       LoadViewState (savedState);
                }
 
-               public void LoadViewState (object savedState)
+               protected virtual void LoadViewState (object savedState)
                {
                        if (savedState == null)
                                return;
@@ -580,7 +526,12 @@ namespace System.Web.UI.WebControls
                                ((IStateManager)ChildNodes).LoadViewState (states [1]);
                }
                
-               public object SaveViewState ()
+               object IStateManager.SaveViewState ()
+               {
+                       return SaveViewState ();
+               }
+
+               protected virtual object SaveViewState ()
                {
                        object[] states = new object[2];
                        states[0] = ViewState.SaveViewState();
@@ -592,8 +543,13 @@ namespace System.Web.UI.WebControls
                        }
                        return null;
                }
-               
-               public void TrackViewState ()
+
+               void IStateManager.TrackViewState ()
+               {
+                       TrackViewState ();
+               }
+
+               protected void TrackViewState ()
                {
                        if (marked) return;
                        marked = true;
@@ -603,80 +559,243 @@ namespace System.Web.UI.WebControls
                                ((IStateManager)nodes).TrackViewState ();
                }
                
-               public bool IsTrackingViewState
-               {
+               bool IStateManager.IsTrackingViewState {
+                       get { return IsTrackingViewState; }
+               }
+
+               protected bool IsTrackingViewState {
                        get { return marked; }
                }
                
                internal void SetDirty ()
                {
-                       ViewState.SetDirty ();
+                       ViewState.SetDirty (true);
+                       if (nodes != null)
+                               nodes.SetDirty ();
                }
                
-               public object Clone ()
+               public virtual object Clone ()
                {
-                       TreeNode nod = new TreeNode ();
+                       TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
                        foreach (DictionaryEntry e in ViewState)
-                               nod.ViewState [(string)e.Key] = e.Value;
+                               nod.ViewState [(string)e.Key] = ((StateItem)e.Value).Value;
                                
                        foreach (TreeNode c in ChildNodes)
                                nod.ChildNodes.Add ((TreeNode)c.Clone ());
                                
                        return nod;
                }
+
+               object ICloneable.Clone ()
+               {
+                       return Clone ();
+               }
                
                internal void Bind (IHierarchyData hierarchyData)
                {
                        this.hierarchyData = hierarchyData;
+                       DataBound = true;
+                       DataPath = hierarchyData.Path;
+                       dataItem = hierarchyData.Item;
+                       
+                       TreeNodeBinding bin = GetBinding ();
+                       if (bin != null) {
+                       
+                               // Bind ImageToolTip property
+
+                               if (bin.ImageToolTipField.Length > 0) {
+                                       ImageToolTip = Convert.ToString (GetBoundPropertyValue (bin.ImageToolTipField));
+                                       if (ImageToolTip.Length == 0)
+                                               ImageToolTip = bin.ImageToolTip;
+                               } else if (bin.ImageToolTip.Length > 0)
+                                       ImageToolTip = bin.ImageToolTip;
+                                       
+                               // Bind ImageUrl property
+
+                               if (bin.ImageUrlField.Length > 0) {
+                                       ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
+                                       if (ImageUrl.Length == 0)
+                                               ImageUrl = bin.ImageUrl;
+                               } else if (bin.ImageUrl.Length > 0)
+                                       ImageUrl = bin.ImageUrl;
+                                       
+                               // Bind NavigateUrl property
+
+                               if (bin.NavigateUrlField.Length > 0) {
+                                       NavigateUrl = Convert.ToString (GetBoundPropertyValue (bin.NavigateUrlField));
+                                       if (NavigateUrl.Length == 0)
+                                               NavigateUrl = bin.NavigateUrl;
+                               } else if (bin.NavigateUrl.Length > 0)
+                                       NavigateUrl = bin.NavigateUrl;
+                                       
+                               // Bind PopulateOnDemand property
+                               
+                               if (bin.HasPropertyValue ("PopulateOnDemand"))
+                                       PopulateOnDemand = bin.PopulateOnDemand;
+                               
+                               // Bind SelectAction property
+                                       
+                               if (bin.HasPropertyValue ("SelectAction"))
+                                       SelectAction = bin.SelectAction;
+                               
+                               // Bind ShowCheckBox property
+                                       
+                               if (bin.HasPropertyValue ("ShowCheckBox"))
+                                       ShowCheckBox = bin.ShowCheckBox;
+                                       
+                               // Bind Target property
+
+                               if (bin.TargetField.Length > 0) {
+                                       Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
+                                       if (Target.Length == 0)
+                                               Target = bin.Target;
+                               } else if (bin.Target.Length > 0)
+                                       Target = bin.Target;
+                                       
+                               // Bind Text property
+                               string text = null;
+                               if (bin.TextField.Length > 0) {
+                                       text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
+                                       if (bin.FormatString.Length > 0)
+                                               text = string.Format (bin.FormatString, text);
+                               }
+                               if (String.IsNullOrEmpty (text)) {
+                                       if (bin.Text.Length > 0)
+                                               text = bin.Text;
+                                       else if (bin.Value.Length > 0)
+                                               text = bin.Value;
+                               }
+                               if (!String.IsNullOrEmpty (text))
+                                       Text = text;
+                                       
+                               // Bind ToolTip property
+
+                               if (bin.ToolTipField.Length > 0) {
+                                       ToolTip = Convert.ToString (GetBoundPropertyValue (bin.ToolTipField));
+                                       if (ToolTip.Length == 0)
+                                               ToolTip = bin.ToolTip;
+                               } else if (bin.ToolTip.Length > 0)
+                                       ToolTip = bin.ToolTip;
+                                       
+                               // Bind Value property
+                               string value = null;
+                               if (bin.ValueField.Length > 0) {
+                                       value = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
+                               }
+                               if (String.IsNullOrEmpty (value)) {
+                                       if (bin.Value.Length > 0)
+                                               value = bin.Value;
+                                       else if (bin.Text.Length > 0)
+                                               value = bin.Text;
+                               }
+                               if (!String.IsNullOrEmpty (value))
+                                       Value = value;
+                       } else {
+                               Text = Value = GetDefaultBoundText ();
+                       }
+
+                       INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
+                       if (navigateUIData != null) {
+                               SelectAction = TreeNodeSelectAction.None;
+                               Text = navigateUIData.ToString ();
+                               NavigateUrl = navigateUIData.NavigateUrl;
+                               ToolTip = navigateUIData.Description;
+                       }
+               }
+               
+               internal void SetDataItem (object item)
+               {
+                       dataItem = item;
+               }
+               
+               internal void SetDataPath (string path)
+               {
+                       DataPath = path;
+               }
+               
+               internal void SetDataBound (bool bound)
+               {
+                       DataBound = bound;
+               }
+               
+               string GetDefaultBoundText ()
+               {
+                       if (hierarchyData != null)
+                               return hierarchyData.ToString ();
+                       else if (dataItem != null)
+                               return dataItem.ToString ();
+                       else
+                               return string.Empty;
                }
                
+               string GetDataItemType ()
+               {
+                       if (hierarchyData != null)
+                               return hierarchyData.Type;
+                       else if (dataItem != null)
+                               return dataItem.GetType().ToString ();
+                       else
+                               return string.Empty;
+               }
+                               
                internal bool IsParentNode {
-                       get { return ChildNodes.Count > 0 && Parent != null; }
+                       get { return ChildNodes.Count > 0 || (PopulateOnDemand && !Populated); }
                }
                
                internal bool IsLeafNode {
-                       get { return ChildNodes.Count == 0; }
+                       get { return !IsParentNode; }
                }
                
                internal bool IsRootNode {
-                       get { return ChildNodes.Count > 0 && Parent == null; }
+                       get { return Depth == 0; }
                }
                
                TreeNodeBinding GetBinding ()
                {
-                       if (tree == null) return null;
-                       if (gotBinding) return binding;
-                       binding = tree.FindBindingForNode (hierarchyData.Type, Depth);
+                       if (tree == null)
+                               return null;
+                       if (gotBinding)
+                               return binding;
+                       binding = tree.FindBindingForNode (GetDataItemType (), Depth);
                        gotBinding = true;
                        return binding;
                }
                
                object GetBoundPropertyValue (string name)
                {
-                       if (boundProperties == null)
-                               boundProperties = TypeDescriptor.GetProperties (hierarchyData);
+                       if (boundProperties == null) {
+                               if (hierarchyData != null)
+                                       boundProperties = TypeDescriptor.GetProperties (hierarchyData);
+                               else
+                                       boundProperties = TypeDescriptor.GetProperties (dataItem);
+                       }
                        
                        PropertyDescriptor prop = boundProperties.Find (name, true);
                        if (prop == null)
                                throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
-                       return prop.GetValue (hierarchyData);
+                               
+                       if (hierarchyData != null)
+                               return prop.GetValue (hierarchyData);
+                       else
+                               return prop.GetValue (dataItem);
                }
 
-               void FillBoundChildren ()
+               internal void BeginRenderText (HtmlTextWriter writer)
+               {
+                       RenderPreText (writer);
+               }
+               
+               internal void EndRenderText (HtmlTextWriter writer)
+               {
+                       RenderPostText (writer);
+               }
+               
+               protected virtual void RenderPreText (HtmlTextWriter writer)
+               {
+               }
+               
+               protected virtual void RenderPostText (HtmlTextWriter writer)
                {
-                       nodes = new TreeNodeCollection (this);
-                       if (!hierarchyData.HasChildren) return;
-                       if (tree.MaxDataBindDepth != -1 && Depth >= tree.MaxDataBindDepth) return;
-
-                       IHierarchicalEnumerable e = hierarchyData.GetChildren ();
-                       foreach (object obj in e) {
-                               IHierarchyData hdata = e.GetHierarchyData (obj);
-                               TreeNode node = new TreeNode ();
-                               node.Bind (hdata);
-                               nodes.Add (node);
-                       }
                }
        }
 }
-
-#endif