In corlib/System.Runtime.InteropServices:
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / TreeNode.cs
1 //
2 // System.Web.UI.WebControls.TreeNode.cs
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2004 Novell, Inc (http://www.novell.com)
8 //
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:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
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.
27 //
28 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
29 //
30
31 #if NET_2_0
32
33 using System;
34 using System.Collections;
35 using System.Text;
36 using System.ComponentModel;
37 using System.Web.UI;
38
39 namespace System.Web.UI.WebControls
40 {
41         [ParseChildrenAttribute (true, "ChildNodes")]
42         public class TreeNode: IStateManager, ICloneable
43         {
44                 StateBag ViewState = new StateBag ();
45                 TreeNodeCollection nodes;
46                 bool marked;
47                 TreeView tree;
48                 TreeNode parent;
49                 int index;
50                 string path;
51                 int depth = -1;
52                 
53                 object dataItem;
54                 IHierarchyData hierarchyData;
55
56                 bool gotBinding;
57                 TreeNodeBinding binding;
58                 PropertyDescriptorCollection boundProperties;
59                 
60                 internal TreeNode (TreeView tree)
61                 {
62                         Tree = tree;
63                 }
64                 
65                 public TreeNode ()
66                 {
67                 }
68                 
69                 public TreeNode (string text)
70                 {
71                         Text = text;
72                 }
73                 
74                 public TreeNode (string text, string value)
75                 {
76                         Text = text;
77                         Value = value;
78                 }
79                 
80                 public TreeNode (string text, string value, string imageUrl)
81                 {
82                         Text = text;
83                         Value = value;
84                         ImageUrl = imageUrl;
85                 }
86                 
87                 public TreeNode (string text, string value, string imageUrl, string navigateUrl, string target)
88                 {
89                         Text = text;
90                         Value = value;
91                         ImageUrl = imageUrl;
92                         NavigateUrl = navigateUrl;
93                         Target = target;
94                 }
95                 
96                 [MonoTODO ("Not implemented")]
97                 protected TreeNode (TreeView owner, bool isRoot)
98                 {
99                         throw new NotImplementedException ();
100                 }
101
102                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
103                 [Browsable (false)]
104                 public int Depth {
105                         get {
106                                 if (depth != -1) return depth;
107                                 depth = 0;
108                                 TreeNode nod = parent;
109                                 while (nod != null) {
110                                         depth++;
111                                         nod = nod.parent;
112                                 }
113                                 return depth;
114                         }
115                 }
116                 
117                 void ResetPathData ()
118                 {
119                         path = null;
120                         depth = -1;
121                         gotBinding = false;
122                 }
123                 
124                 internal TreeView Tree {
125                         get { return tree; }
126                         set {
127                                 if (SelectedFlag) {
128                                         if (value != null)
129                                                 value.SetSelectedNode (this, false);
130                                         if (tree != null)
131                                                 tree.SetSelectedNode (null, false);
132                                 }
133                                 tree = value;
134                                 if (nodes != null)
135                                         nodes.SetTree (tree);
136                                 ResetPathData ();
137                                 if (PopulateOnDemand && !Populated && Expanded.HasValue && Expanded.Value)
138                                         Populate ();
139                         }
140                 }
141                 
142                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
143                 [DefaultValue (false)]
144                 [Browsable (false)]
145                 public bool DataBound {
146                         get { return ViewState ["DataBound"] == null ? false : (bool) ViewState ["DataBound"]; }
147                         private set { ViewState ["DataBound"] = value; }
148                 }
149                 
150                 [DefaultValue (null)]
151                 [Browsable (false)]
152                 public object DataItem {
153                         get {
154                                 return dataItem;
155                         }
156                 }
157                 
158                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
159                 [DefaultValue ("")]
160                 [Browsable (false)]
161                 public string DataPath {
162                         get { return ViewState ["DataPath"] == null ? String.Empty : (String) ViewState ["DataPath"]; }
163                         private set { ViewState ["DataPath"] = value; }
164                 }
165                 
166                 [DefaultValue (false)]
167                 public bool Checked {
168                         get {
169                                 object o = ViewState ["Checked"];
170                                 if (o != null) return (bool)o;
171                                 return false;
172                         }
173                         set {
174                                 ViewState ["Checked"] = value;
175                                 if (tree != null)
176                                         tree.NotifyCheckChanged (this);
177                         }
178                 }
179
180                 [DefaultValue (null)]
181                 [MergableProperty (false)]
182                 [Browsable (false)]
183                 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
184                 public TreeNodeCollection ChildNodes {
185                         get {
186                                 if (nodes == null) {
187                                         nodes = new TreeNodeCollection (this);
188                                                 
189                                         if (IsTrackingViewState)
190                                                 ((IStateManager)nodes).TrackViewState();
191                                 }
192                                 return nodes;
193                         }
194                 }
195                 
196                 [DefaultValue (null)]
197                 public bool? Expanded {
198                         get {
199                                 object o = ViewState ["Expanded"];
200                                 return (bool?)o;
201                         }
202                         set {
203                                 bool? current = (bool?) ViewState ["Expanded"];
204                                 if (current == value)
205                                         return;
206                                 ViewState ["Expanded"] = value;
207                                 if (tree != null)
208                                         tree.NotifyExpandedChanged (this);
209                                 if (PopulateOnDemand && !Populated && value.HasValue && value.Value)
210                                         Populate ();
211                         }
212                 }
213
214                 [Localizable (true)]
215                 [DefaultValue ("")]
216                 public string ImageToolTip {
217                         get {
218                                 object o = ViewState ["ImageToolTip"];
219                                 if (o != null) return (string)o;
220                                 return "";
221                         }
222                         set {
223                                 ViewState ["ImageToolTip"] = value;
224                         }
225                 }
226                 
227                 [DefaultValue ("")]
228                 [UrlProperty]
229                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
230                 public string ImageUrl {
231                         get {
232                                 object o = ViewState ["ImageUrl"];
233                                 if (o != null) return (string)o;
234                                 return "";
235                         }
236                         set {
237                                 ViewState ["ImageUrl"] = value;
238                         }
239                 }
240
241                 [DefaultValue ("")]
242                 [UrlProperty]
243                 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
244                 public string NavigateUrl {
245                         get {
246                                 object o = ViewState ["NavigateUrl"];
247                                 if (o != null) return (string)o;
248                                 return "";
249                         }
250                         set {
251                                 ViewState ["NavigateUrl"] = value;
252                         }
253                 }
254
255                 [DefaultValue (false)]
256                 public bool PopulateOnDemand {
257                         get {
258                                 object o = ViewState ["PopulateOnDemand"];
259                                 if (o != null) return (bool)o;
260                                 return false;
261                         }
262                         set {
263                                 ViewState ["PopulateOnDemand"] = value;
264                         }
265                 }
266
267                 [DefaultValue (TreeNodeSelectAction.Select)]
268                 public TreeNodeSelectAction SelectAction {
269                         get {
270                                 object o = ViewState ["SelectAction"];
271                                 if (o != null) return (TreeNodeSelectAction)o;
272                                 return TreeNodeSelectAction.Select;
273                         }
274                         set {
275                                 ViewState ["SelectAction"] = value;
276                         }
277                 }
278
279                 [DefaultValue (null)]
280                 public bool? ShowCheckBox {
281                         get {
282                                 object o = ViewState ["ShowCheckBox"];
283                                 return (bool?)o;
284                         }
285                         set {
286                                 ViewState ["ShowCheckBox"] = value;
287                         }
288                 }
289
290                 internal bool ShowCheckBoxInternal {
291                         get {
292                                 if (ShowCheckBox.HasValue)
293                                         return ShowCheckBox.Value;
294                                 else
295                                         return (Tree.ShowCheckBoxes == TreeNodeTypes.All) ||
296                                                  ((Tree.ShowCheckBoxes & TreeNodeTypes.Leaf) > 0 && IsLeafNode) ||
297                                                  ((Tree.ShowCheckBoxes & TreeNodeTypes.Parent) > 0 && IsParentNode && Parent != null) ||
298                                                  ((Tree.ShowCheckBoxes & TreeNodeTypes.Root) > 0 && Parent == null && ChildNodes.Count > 0);
299                         }
300                 }
301                 
302                 [DefaultValue ("")]
303                 public string Target {
304                         get {
305                                 object o = ViewState ["Target"];
306                                 if(o != null) return (string)o;
307                                 return "";
308                         }
309                         set {
310                                 ViewState ["Target"] = value;
311                         }
312                 }
313
314                 [Localizable (true)]
315                 [DefaultValue ("")]
316                 [WebSysDescription ("The display text of the tree node.")]
317                 public string Text {
318                         get {
319                                 object o = ViewState ["Text"];
320                                 if (o != null) return (string)o;
321                                 return "";
322                         }
323                         set {
324                                 ViewState ["Text"] = value;
325                         }
326                 }
327
328                 [Localizable (true)]
329                 [DefaultValue ("")]
330                 public string ToolTip {
331                         get {
332                                 object o = ViewState ["ToolTip"];
333                                 if(o != null) return (string)o;
334                                 return "";
335                         }
336                         set {
337                                 ViewState ["ToolTip"] = value;
338                         }
339                 }
340
341                 [Localizable (true)]
342                 [DefaultValue ("")]
343                 public string Value {
344                         get {
345                                 object o = ViewState ["Value"];
346                                 if(o != null) return (string)o;
347                                 return "";
348                         }
349                         set {
350                                 ViewState ["Value"] = value;
351                         }
352                 }
353                 
354                 [DefaultValue (false)]
355                 public bool Selected {
356                         get {
357                                 return SelectedFlag;
358                         }
359                         set {
360                                 SelectedFlag = value;
361                                 
362                                 if (tree != null) {
363                                         if (!value && tree.SelectedNode == this)
364                                                 tree.SetSelectedNode (null, false);
365                                         else if (value)
366                                                 tree.SetSelectedNode (this, false);
367                                 }
368                         }
369                 }
370                 
371                 internal virtual bool SelectedFlag {
372                         get {
373                                 object o = ViewState ["Selected"];
374                                 if(o != null) return (bool)o;
375                                 return false;
376                         }
377                         set {
378                                 ViewState ["Selected"] = value;
379                         }
380                 }
381                 
382                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
383                 [Browsable (false)]
384                 public TreeNode Parent {
385                         get { return parent; }
386                 }
387                 
388                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
389                 [Browsable (false)]
390                 public string ValuePath {
391                         get {
392                                 if (tree == null) return Value;
393                                 
394                                 StringBuilder sb = new StringBuilder (Value);
395                                 TreeNode node = parent;
396                                 while (node != null) {
397                                         sb.Insert (0, tree.PathSeparator);
398                                         sb.Insert (0, node.Value);
399                                         node = node.Parent;
400                                 }
401                                 return sb.ToString ();
402                         }
403                 }
404                 
405                 internal int Index {
406                         get { return index; }
407                         set { index = value; ResetPathData (); }
408                 }
409                 
410                 internal void SetParent (TreeNode node) {
411                         parent = node;
412                         ResetPathData ();
413                 }
414                 
415                 internal string Path {
416                         get {
417                                 if (path != null) return path;
418                                 StringBuilder sb = new StringBuilder (index.ToString());
419                                 TreeNode node = parent;
420                                 while (node != null) {
421                                         sb.Insert (0, '_');
422                                         sb.Insert (0, node.Index.ToString ());
423                                         node = node.Parent;
424                                 }
425                                 path = sb.ToString ();
426                                 return path;
427                         }
428                 }
429                 
430                 internal bool Populated {
431                         get {
432                                 object o = ViewState ["Populated"];
433                                 if (o != null) return (bool) o;
434                                 return false;
435                         }
436                         set {
437                                 ViewState ["Populated"] = value;
438                         }
439                 }
440
441                 internal bool HasChildData {
442                         get { return nodes != null; }
443                 }
444                 
445                 internal void Populate ()
446                 {
447                         if (tree == null)
448                                 return;
449
450                         Populated = true;
451                         tree.NotifyPopulateRequired (this);
452                 }
453                 
454                 public void Collapse ()
455                 {
456                         Expanded = false;
457                 }
458
459                 public void CollapseAll ()
460                 {
461                         SetExpandedRec (false, -1);
462                 }
463
464                 public void Expand ()
465                 {
466                         Expanded = true;
467                 }
468
469                 internal void Expand (int depth)
470                 {
471                         SetExpandedRec (true, depth);
472                 }
473
474                 public void ExpandAll ()
475                 {
476                         SetExpandedRec (true, -1);
477                 }
478                 
479                 void SetExpandedRec (bool expanded, int depth)
480                 {
481                         Expanded = expanded;
482                         if (depth == 0) return;
483                         
484                         foreach (TreeNode nod in ChildNodes)
485                                 nod.SetExpandedRec (expanded, depth - 1);
486                 }
487                 
488                 public void Select ()
489                 {
490                         Selected = true;
491                 }
492                 
493                 public void ToggleExpandState ()
494                 {
495 #if TARGET_JVM //No support for Nullable<bool>.GetValueOrDefault() yet
496                         bool? value = Expanded;
497                         Expanded = value.HasValue ? !value.Value : true;
498 #else
499                         Expanded = !Expanded.GetValueOrDefault(false);
500 #endif
501                 }
502
503                 void IStateManager.LoadViewState (object savedState)
504                 {
505                         LoadViewState (savedState);
506                 }
507
508                 protected virtual void LoadViewState (object savedState)
509                 {
510                         if (savedState == null)
511                                 return;
512
513                         object[] states = (object[]) savedState;
514                         ViewState.LoadViewState (states [0]);
515                         
516                         if (tree != null && SelectedFlag)
517                                 tree.SetSelectedNode (this, true);
518                         
519                         if (!PopulateOnDemand || Populated)
520                                 ((IStateManager)ChildNodes).LoadViewState (states [1]);
521                 }
522                 
523                 object IStateManager.SaveViewState ()
524                 {
525                         return SaveViewState ();
526                 }
527
528                 protected virtual object SaveViewState ()
529                 {
530                         object[] states = new object[2];
531                         states[0] = ViewState.SaveViewState();
532                         states[1] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState());
533                         
534                         for (int i = 0; i < states.Length; i++) {
535                                 if (states [i] != null)
536                                         return states;
537                         }
538                         return null;
539                 }
540
541                 void IStateManager.TrackViewState ()
542                 {
543                         TrackViewState ();
544                 }
545
546                 protected void TrackViewState ()
547                 {
548                         if (marked) return;
549                         marked = true;
550                         ViewState.TrackViewState();
551
552                         if (nodes != null)
553                                 ((IStateManager)nodes).TrackViewState ();
554                 }
555                 
556                 bool IStateManager.IsTrackingViewState {
557                         get { return IsTrackingViewState; }
558                 }
559
560                 protected bool IsTrackingViewState
561                 {
562                         get { return marked; }
563                 }
564                 
565                 internal void SetDirty ()
566                 {
567                         ViewState.SetDirty (true);
568                         if (nodes != null)
569                                 nodes.SetDirty ();
570                 }
571                 
572                 public virtual object Clone ()
573                 {
574                         TreeNode nod = tree != null ? tree.CreateNode () : new TreeNode ();
575                         foreach (DictionaryEntry e in ViewState)
576                                 nod.ViewState [(string)e.Key] = ((StateItem)e.Value).Value;
577                                 
578                         foreach (TreeNode c in ChildNodes)
579                                 nod.ChildNodes.Add ((TreeNode)c.Clone ());
580                                 
581                         return nod;
582                 }
583
584                 object ICloneable.Clone () {
585                         return Clone ();
586                 }
587                 
588                 internal void Bind (IHierarchyData hierarchyData)
589                 {
590                         this.hierarchyData = hierarchyData;
591                         DataBound = true;
592                         DataPath = hierarchyData.Path;
593                         dataItem = hierarchyData.Item;
594                         
595                         TreeNodeBinding bin = GetBinding ();
596                         if (bin != null) {
597                         
598                                 // Bind ImageToolTip property
599
600                                 if (bin.ImageToolTipField.Length > 0) {
601                                         ImageToolTip = Convert.ToString (GetBoundPropertyValue (bin.ImageToolTipField));
602                                         if (ImageToolTip.Length == 0)
603                                                 ImageToolTip = bin.ImageToolTip;
604                                 }
605                                 else if (bin.ImageToolTip.Length > 0)
606                                         ImageToolTip = bin.ImageToolTip;
607                                         
608                                 // Bind ImageUrl property
609
610                                 if (bin.ImageUrlField.Length > 0) {
611                                         ImageUrl = Convert.ToString (GetBoundPropertyValue (bin.ImageUrlField));
612                                         if (ImageUrl.Length == 0)
613                                                 ImageUrl = bin.ImageUrl;
614                                 }
615                                 else if (bin.ImageUrl.Length > 0)
616                                         ImageUrl = bin.ImageUrl;
617                                         
618                                 // Bind NavigateUrl property
619
620                                 if (bin.NavigateUrlField.Length > 0) {
621                                         NavigateUrl = Convert.ToString (GetBoundPropertyValue (bin.NavigateUrlField));
622                                         if (NavigateUrl.Length == 0)
623                                                 NavigateUrl = bin.NavigateUrl;
624                                 }
625                                 else if (bin.NavigateUrl.Length > 0)
626                                         NavigateUrl = bin.NavigateUrl;
627                                         
628                                 // Bind PopulateOnDemand property
629                                 
630                                 if (bin.HasPropertyValue ("PopulateOnDemand"))
631                                         PopulateOnDemand = bin.PopulateOnDemand;
632                                 
633                                 // Bind SelectAction property
634                                         
635                                 if (bin.HasPropertyValue ("SelectAction"))
636                                         SelectAction = bin.SelectAction;
637                                 
638                                 // Bind ShowCheckBox property
639                                         
640                                 if (bin.HasPropertyValue ("ShowCheckBox"))
641                                         ShowCheckBox = bin.ShowCheckBox;
642                                         
643                                 // Bind Target property
644
645                                 if (bin.TargetField.Length > 0) {
646                                         Target = Convert.ToString (GetBoundPropertyValue (bin.TargetField));
647                                         if (Target.Length == 0)
648                                                 Target = bin.Target;
649                                 }
650                                 else if (bin.Target.Length > 0)
651                                         Target = bin.Target;
652                                         
653                                 // Bind Text property
654                                         
655                                 if (bin.TextField.Length > 0) {
656                                         Text = Convert.ToString (GetBoundPropertyValue (bin.TextField));
657                                         if (bin.FormatString.Length > 0)
658                                                 Text = string.Format (bin.FormatString, Text);
659                                         if (Text.Length == 0)
660                                                 Text = bin.Text;
661                                         if (Text.Length == 0)
662                                                 Text = bin.Value;
663                                         if (Text.Length == 0 && bin.ValueField.Length > 0)
664                                                 Text = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
665                                 }
666                                 else if (bin.Text.Length > 0)
667                                         Text = bin.Text;
668                                 else if (bin.Value.Length > 0)
669                                         Text = bin.Value;
670                                 else
671                                         Text = GetDefaultBoundText ();
672                                         
673                                 // Bind ToolTip property
674
675                                 if (bin.ToolTipField.Length > 0) {
676                                         ToolTip = Convert.ToString (GetBoundPropertyValue (bin.ToolTipField));
677                                         if (ToolTip.Length == 0)
678                                                 ToolTip = bin.ToolTip;
679                                 }
680                                 else if (bin.ToolTip.Length > 0)
681                                         ToolTip = bin.ToolTip;
682                                         
683                                 // Bind Value property
684
685                                 if (bin.ValueField.Length > 0) {
686                                         Value = Convert.ToString (GetBoundPropertyValue (bin.ValueField));
687                                         if (Value.Length == 0)
688                                                 Value = bin.Value;
689                                         if (Value.Length == 0)
690                                                 Value = bin.Text;
691                                         if(Value.Length == 0 && bin.TextField.Length > 0)
692                                                 Value = Convert.ToString (GetBoundPropertyValue (bin.TextField));
693                                 }
694                                 else if (bin.Value.Length > 0)
695                                         Value = bin.Value;
696                                 else if (bin.Text.Length > 0)
697                                         Value = bin.Text;
698                                 else if (Text.Length > 0)
699                                         Value = Text;
700                                 else
701                                         Value = GetDefaultBoundText ();
702                         } else {
703                                 Text = Value = GetDefaultBoundText ();
704                         }
705
706                         INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
707                         if (navigateUIData != null) {
708                                 Text = navigateUIData.ToString ();
709                                 NavigateUrl = navigateUIData.NavigateUrl;
710                         }
711                 }
712                 
713                 internal void SetDataItem (object item)
714                 {
715                         dataItem = item;
716                 }
717                 
718                 internal void SetDataPath (string path)
719                 {
720                         DataPath = path;
721                 }
722                 
723                 internal void SetDataBound (bool bound)
724                 {
725                         DataBound = bound;
726                 }
727                 
728                 string GetDefaultBoundText ()
729                 {
730                         if (hierarchyData != null) return hierarchyData.ToString ();
731                         else if (dataItem != null) return dataItem.ToString ();
732                         else return string.Empty;
733                 }
734                 
735                 string GetDataItemType ()
736                 {
737                         if (hierarchyData != null) return hierarchyData.Type;
738                         else if (dataItem != null) return dataItem.GetType().ToString ();
739                         else return string.Empty;
740                 }
741                                 
742                 internal bool IsParentNode {
743                         get { return ChildNodes.Count > 0 || (PopulateOnDemand && !Populated); }
744                 }
745                 
746                 internal bool IsLeafNode {
747                         get { return !IsParentNode; }
748                 }
749                 
750                 internal bool IsRootNode {
751                         get { return Depth == 0; }
752                 }
753                 
754                 TreeNodeBinding GetBinding ()
755                 {
756                         if (tree == null) return null;
757                         if (gotBinding) return binding;
758                         binding = tree.FindBindingForNode (GetDataItemType (), Depth);
759                         gotBinding = true;
760                         return binding;
761                 }
762                 
763                 object GetBoundPropertyValue (string name)
764                 {
765                         if (boundProperties == null) {
766                                 if (hierarchyData != null)
767                                         boundProperties = TypeDescriptor.GetProperties (hierarchyData);
768                                 else
769                                         boundProperties = TypeDescriptor.GetProperties (dataItem);
770                         }
771                         
772                         PropertyDescriptor prop = boundProperties.Find (name, true);
773                         if (prop == null)
774                                 throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
775                                 
776                         if (hierarchyData != null)
777                                 return prop.GetValue (hierarchyData);
778                         else
779                                 return prop.GetValue (dataItem);
780                 }
781
782                 internal void BeginRenderText (HtmlTextWriter writer)
783                 {
784                         RenderPreText (writer);
785                 }
786                 
787                 internal void EndRenderText (HtmlTextWriter writer)
788                 {
789                         RenderPostText (writer);
790                 }
791                 
792                 protected virtual void RenderPreText (HtmlTextWriter writer)
793                 {
794                 }
795                 
796                 protected virtual void RenderPostText (HtmlTextWriter writer)
797                 {
798                 }
799         }
800 }
801
802 #endif