2009-03-18 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / ControlBuilder.cs
1 //
2 // System.Web.UI.ControlBuilder.cs
3 //
4 // Authors:
5 //      Duncan Mak  (duncan@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (C) 2002, 2003 Ximian, Inc. (http://www.ximian.com)
9 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Collections;
32 using System.Configuration;
33 using System.CodeDom;
34 using System.Globalization;
35 using System.Reflection;
36 using System.Security.Permissions;
37 using System.Web.Compilation;
38 using System.Web.Configuration;
39 using System.IO;
40 using System.Web.UI.WebControls;
41
42 namespace System.Web.UI {
43
44         // CAS
45         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47         public class ControlBuilder
48         {
49                 internal static readonly BindingFlags FlagsNoCase = BindingFlags.Public |
50                         BindingFlags.Instance |
51                         BindingFlags.Static |
52                         BindingFlags.IgnoreCase;
53
54                 ControlBuilder myNamingContainer;
55                 TemplateParser parser;
56                 Type parserType;
57                 ControlBuilder parentBuilder;
58                 Type type;             
59                 string tagName;
60                 string originalTagName;
61                 string id;
62                 IDictionary attribs;
63                 int line;
64                 string fileName;
65                 bool childrenAsProperties;
66                 bool isIParserAccessor = true;
67                 bool hasAspCode;
68                 ControlBuilder defaultPropertyBuilder;
69                 ArrayList children;
70                 ArrayList templateChildren;
71                 static int nextID;
72
73                 bool haveParserVariable;
74                 CodeMemberMethod method;
75                 CodeStatementCollection methodStatements;
76                 CodeMemberMethod renderMethod;
77                 int renderIndex;
78                 bool isProperty;
79                 ILocation location;
80                 ArrayList otherTags;
81                 
82                 public ControlBuilder ()
83                 {
84                 }
85
86                 internal ControlBuilder (TemplateParser parser,
87                                          ControlBuilder parentBuilder,
88                                          Type type,
89                                          string tagName,
90                                          string id,
91                                          IDictionary attribs,
92                                          int line,
93                                          string sourceFileName)
94
95                 {
96                         this.parser = parser;
97                         this.parserType = parser != null ? parser.GetType () : null;
98                         this.parentBuilder = parentBuilder;
99                         this.type = type;
100                         this.tagName = tagName;
101                         this.id = id;
102                         this.attribs = attribs;
103                         this.line = line;
104                         this.fileName = sourceFileName;
105                 }
106
107                 internal void EnsureOtherTags ()
108                 {
109                         if (otherTags == null)
110                                 otherTags = new ArrayList ();
111                 }
112
113                 internal ControlBuilder ParentBuilder {
114                         get { return parentBuilder; }
115                 }
116
117                 internal IDictionary Attributes {
118                         get { return attribs; }
119                 }
120
121                 internal int Line {
122                         get { return line; }
123                         set { line = value; }
124                 }
125
126                 internal string FileName {
127                         get { return fileName; }
128                         set { fileName = value; }
129                 }
130
131                 internal ControlBuilder DefaultPropertyBuilder {
132                         get { return defaultPropertyBuilder; }
133                 }
134
135                 internal bool HaveParserVariable {
136                         get { return haveParserVariable; }
137                         set { haveParserVariable = value; }
138                 }
139
140                 internal CodeMemberMethod Method {
141                         get { return method; }
142                         set { method = value; }
143                 }
144
145                 internal CodeStatementCollection MethodStatements {
146                         get { return methodStatements; }
147                         set { methodStatements = value; }
148                 }
149
150                 internal CodeMemberMethod RenderMethod {
151                         get { return renderMethod; }
152                         set { renderMethod = value; }
153                 }
154
155                 internal int RenderIndex {
156                         get { return renderIndex; }
157                 }
158
159                 internal bool IsProperty {
160                         get { return isProperty; }
161                 }
162
163                 internal ILocation Location {
164                         get { return location; }
165                         set { location = value; }
166                 }
167         
168                 internal ArrayList OtherTags {
169                         get { return otherTags; }
170                 }
171
172                 public Type ControlType {
173                         get { return type; }
174                 }
175
176                 protected bool FChildrenAsProperties {
177                         get { return childrenAsProperties; }
178                 }
179
180                 protected bool FIsNonParserAccessor {
181                         get { return !isIParserAccessor; }
182                 }
183
184                 public bool HasAspCode {
185                         get { return hasAspCode; }
186                 }
187
188                 public string ID {
189                         get { return id; }
190                         set { id = value; }
191                 }
192
193                 internal ArrayList Children {
194                         get { return children; }
195                 }
196
197                 internal ArrayList TemplateChildren {
198                         get { return templateChildren; }
199                 }
200                 
201                 internal void SetControlType (Type t)
202                 {
203                         type = t;
204                 }
205                 
206                 protected bool InDesigner {
207                         get { return false; }
208                 }
209
210                 public Type NamingContainerType {
211                         get {
212                                 ControlBuilder cb = myNamingContainer;
213                                 
214                                 if (cb == null)
215                                         return typeof (Control);
216
217                                 return cb.ControlType;
218                         }
219                 }
220
221                 ControlBuilder MyNamingContainer {
222                         get {
223                                 if (myNamingContainer == null) {
224                                         Type controlType = parentBuilder != null ? parentBuilder.ControlType : null;
225                                         
226                                         if (parentBuilder == null && controlType == null)
227                                                 myNamingContainer = null;
228                                         else if (parentBuilder is TemplateBuilder)
229                                                 myNamingContainer = parentBuilder;
230                                         else if (controlType != null && typeof (INamingContainer).IsAssignableFrom (controlType))
231                                                 myNamingContainer = parentBuilder;
232                                         else
233                                                 myNamingContainer = parentBuilder.MyNamingContainer;
234                                 }
235
236                                 return myNamingContainer;
237                         }
238                 }
239                         
240 #if NET_2_0
241                 public virtual
242 #else
243                 internal
244 #endif
245                 Type BindingContainerType {
246                         get {
247                                 ControlBuilder cb = (this is TemplateBuilder && !(this is RootBuilder)) ? this : MyNamingContainer;
248                                 
249                                 if (cb == null) {
250                                         if (this is RootBuilder && parserType == typeof (PageParser)) 
251                                                 return typeof (Page);
252                                         
253                                         return typeof (Control);
254                                 }
255
256 #if NET_2_0
257                                 if (cb != this && cb is ContentBuilderInternal && !typeof (INonBindingContainer).IsAssignableFrom (cb.BindingContainerType))
258                                         return cb.BindingContainerType;
259 #endif
260
261                                 Type ct;
262                                 if (cb is TemplateBuilder) {
263                                         ct = ((TemplateBuilder) cb).ContainerType;
264                                         if (typeof (INonBindingContainer).IsAssignableFrom (ct))
265                                                 return MyNamingContainer.BindingContainerType;
266                                         
267                                         if (ct != null)
268                                                 return ct;
269
270                                         ct = cb.ControlType;
271                                         if (ct == null)
272                                                 return typeof (Control);
273                                         
274                                         if (typeof (INonBindingContainer).IsAssignableFrom (ct) || !typeof (INamingContainer).IsAssignableFrom (ct))
275                                                 return MyNamingContainer.BindingContainerType;
276
277                                         return ct;
278                                 }
279
280                                 ct = cb.ControlType;
281                                 if (ct == null)
282                                         return typeof (Control);
283                                 
284                                 if (typeof (INonBindingContainer).IsAssignableFrom (ct) || !typeof (INamingContainer).IsAssignableFrom (ct))
285                                         return MyNamingContainer.BindingContainerType;
286                                 
287                                 return cb.ControlType;
288                         }
289                 }
290
291                 internal TemplateBuilder ParentTemplateBuilder {
292                         get {
293                                 if (parentBuilder == null)
294                                         return null;
295                                 else if (parentBuilder is TemplateBuilder)
296                                         return (TemplateBuilder) parentBuilder;
297                                 else
298                                         return parentBuilder.ParentTemplateBuilder;
299                         }
300                 }
301
302                 protected TemplateParser Parser {
303                         get { return parser; }
304                 }
305
306                 public string TagName {
307                         get { return tagName; }
308                 }
309
310                 internal string OriginalTagName {
311                         get {
312                                 if (originalTagName == null || originalTagName.Length == 0)
313                                         return TagName;
314                                 return originalTagName;
315                         }
316                 }
317                 
318                 internal RootBuilder Root {
319                         get {
320                                 if (GetType () == typeof (RootBuilder))
321                                         return (RootBuilder) this;
322
323                                 return (RootBuilder) parentBuilder.Root;
324                         }
325                 }
326
327                 internal bool ChildrenAsProperties {
328                         get { return childrenAsProperties; }
329                 }
330
331                 internal string GetAttribute (string name)
332                 {
333                         if (attribs == null)
334                                 return null;
335
336                         return attribs [name] as string;
337                 }
338
339                 internal void IncreaseRenderIndex ()
340                 {
341                         renderIndex++;
342                 }
343                 
344                 void AddChild (object child)
345                 {
346                         if (children == null)
347                                 children = new ArrayList ();
348
349                         children.Add (child);
350                         ControlBuilder cb = child as ControlBuilder;
351                         if (cb != null && cb is TemplateBuilder) {
352                                 if (templateChildren == null)
353                                         templateChildren = new ArrayList ();
354                                 templateChildren.Add (child);
355                         }
356
357 #if NET_2_0
358                         if (parser == null)
359                                 return;
360                         
361                         string tag = cb != null ? cb.TagName : null;
362                         if (String.IsNullOrEmpty (tag))
363                                 return;
364
365                         RootBuilder rb = Root;
366                         AspComponentFoundry foundry = rb != null ? rb.Foundry : null;
367                         if (foundry == null)
368                                 return;
369                         AspComponent component = foundry.GetComponent (tag);
370                         if (component == null || !component.FromConfig)
371                                 return;
372                         
373                         parser.AddImport (component.Namespace);
374                         parser.AddDependency (component.Source);
375 #endif
376                 }
377                 
378                 public virtual bool AllowWhitespaceLiterals ()
379                 {
380                         return true;
381                 }
382
383                 public virtual void AppendLiteralString (string s)
384                 {
385                         if (s == null || s.Length == 0)
386                                 return;
387
388                         if (childrenAsProperties || !isIParserAccessor) {
389                                 if (defaultPropertyBuilder != null) {
390                                         defaultPropertyBuilder.AppendLiteralString (s);
391                                 } else if (s.Trim ().Length != 0) {
392                                         throw new HttpException (String.Format ("Literal content not allowed for '{0}' {1} \"{2}\"",
393                                                                                 tagName, GetType (), s));
394                                 }
395
396                                 return;
397                         }
398                         
399                         if (!AllowWhitespaceLiterals () && s.Trim ().Length == 0)
400                                 return;
401
402                         if (HtmlDecodeLiterals ())
403                                 s = HttpUtility.HtmlDecode (s);
404
405                         AddChild (s);
406                 }
407
408                 public virtual void AppendSubBuilder (ControlBuilder subBuilder)
409                 {
410                         subBuilder.OnAppendToParentBuilder (this);
411                         
412                         subBuilder.parentBuilder = this;
413                         if (childrenAsProperties) {
414                                 AppendToProperty (subBuilder);
415                                 return;
416                         }
417
418                         if (typeof (CodeRenderBuilder).IsAssignableFrom (subBuilder.GetType ())) {
419                                 AppendCode (subBuilder);
420                                 return;
421                         }
422
423                         AddChild (subBuilder);
424                 }
425
426                 void AppendToProperty (ControlBuilder subBuilder)
427                 {
428                         if (typeof (CodeRenderBuilder) == subBuilder.GetType ())
429                                 throw new HttpException ("Code render not supported here.");
430
431                         if (defaultPropertyBuilder != null) {
432                                 defaultPropertyBuilder.AppendSubBuilder (subBuilder);
433                                 return;
434                         }
435
436                         AddChild (subBuilder);
437                 }
438
439                 void AppendCode (ControlBuilder subBuilder)
440                 {
441                         if (type != null && !(typeof (Control).IsAssignableFrom (type)))
442                                 throw new HttpException ("Code render not supported here.");
443
444                         if (typeof (CodeRenderBuilder) == subBuilder.GetType ())
445                                 hasAspCode = true;
446
447                         AddChild (subBuilder);
448                 }
449
450                 public virtual void CloseControl ()
451                 {
452                 }
453
454 #if NET_2_0             
455                 static Type MapTagType (Type tagType)
456                 {
457                         if (tagType == null)
458                                 return null;
459                         
460                         PagesSection ps = WebConfigurationManager.GetWebApplicationSection ("system.web/pages") as PagesSection;
461                         if (ps == null)
462                                 return tagType;
463
464                         TagMapCollection tags = ps.TagMapping;
465                         if (tags == null || tags.Count == 0)
466                                 return tagType;
467                         
468                         string tagTypeName = tagType.ToString ();
469                         Type mappedType, originalType;
470                         string originalTypeName = String.Empty, mappedTypeName = String.Empty;
471                         bool missingType;
472                         Exception error;
473                         
474                         foreach (TagMapInfo tmi in tags) {
475                                 error = null;
476                                 originalType = null;
477                                 
478                                 try {
479                                         originalTypeName = tmi.TagType;
480                                         originalType = HttpApplication.LoadType (originalTypeName);
481                                         if (originalType == null)
482                                                 missingType = true;
483                                         else
484                                                 missingType = false;
485                                 } catch (Exception ex) {
486                                         missingType = true;
487                                         error = ex;
488                                 }
489                                 if (missingType)
490                                         throw new HttpException (String.Format ("Could not load type {0}", originalTypeName), error);
491                                 
492                                 if (originalTypeName == tagTypeName) {
493                                         mappedTypeName = tmi.MappedTagType;
494                                         error = null;
495                                         mappedType = null;
496                                         
497                                         try {
498                                                 mappedType = HttpApplication.LoadType (mappedTypeName);
499                                                 if (mappedType == null)
500                                                         missingType = true;
501                                                 else
502                                                         missingType = false;
503                                         } catch (Exception ex) {
504                                                 missingType = true;
505                                                 error = ex;
506                                         }
507
508                                         if (missingType)
509                                                 throw new HttpException (String.Format ("Could not load type {0}", mappedTypeName),
510                                                                          error);
511                                         
512                                         if (!mappedType.IsSubclassOf (originalType))
513                                                 throw new ConfigurationErrorsException (
514                                                         String.Format ("The specified type '{0}' used for mapping must inherit from the original type '{1}'.", mappedTypeName, originalTypeName));
515
516                                         return mappedType;
517                                 }
518                         }
519                         
520                         return tagType;
521                 }
522 #endif
523
524                 public static ControlBuilder CreateBuilderFromType (TemplateParser parser,
525                                                                     ControlBuilder parentBuilder,
526                                                                     Type type,
527                                                                     string tagName,
528                                                                     string id,
529                                                                     IDictionary attribs,
530                                                                     int line,
531                                                                     string sourceFileName)
532                 {
533
534                         Type tagType;
535 #if NET_2_0
536                         tagType = MapTagType (type);
537 #else
538                         tagType = type;
539 #endif
540                         ControlBuilder  builder;
541                         object [] atts = tagType.GetCustomAttributes (typeof (ControlBuilderAttribute), true);
542                         if (atts != null && atts.Length > 0) {
543                                 ControlBuilderAttribute att = (ControlBuilderAttribute) atts [0];
544                                 builder = (ControlBuilder) Activator.CreateInstance (att.BuilderType);
545                         } else {
546                                 builder = new ControlBuilder ();
547                         }
548
549                         builder.Init (parser, parentBuilder, tagType, tagName, id, attribs);
550                         builder.line = line;
551                         builder.fileName = sourceFileName;
552                         return builder;
553                 }
554
555                 public virtual Type GetChildControlType (string tagName, IDictionary attribs)
556                 {
557                         return null;
558                 }
559
560                 public virtual bool HasBody ()
561                 {
562                         return true;
563                 }
564
565                 public virtual bool HtmlDecodeLiterals ()
566                 {
567                         return false;
568                 }
569                 
570                 ControlBuilder CreatePropertyBuilder (string propName, TemplateParser parser, IDictionary atts)
571                 {
572                         int idx;
573                         string propertyName;
574                         
575                         if ((idx = propName.IndexOf (':')) >= 0)
576                                 propertyName = propName.Substring (idx + 1);
577                         else
578                                 propertyName = propName;
579                         
580                         PropertyInfo prop = type.GetProperty (propertyName, FlagsNoCase);
581                         if (prop == null) {
582                                 string msg = String.Format ("Property {0} not found in type {1}", propertyName, type);
583                                 throw new HttpException (msg);
584                         }
585
586                         Type propType = prop.PropertyType;
587                         ControlBuilder builder = null;
588                         if (typeof (ICollection).IsAssignableFrom (propType)) {
589                                 builder = new CollectionBuilder ();
590                         } else if (typeof (ITemplate).IsAssignableFrom (propType)) {
591                                 builder = new TemplateBuilder (prop);
592                         } else if (typeof (string) == propType) {
593                                 builder = new StringPropertyBuilder (prop.Name);
594                         } else {
595                                 builder = CreateBuilderFromType (parser, parentBuilder, propType, prop.Name,
596                                                                  null, atts, line, fileName);
597                                 builder.isProperty = true;
598                                 if (idx >= 0)
599                                         builder.originalTagName = propName;
600                                 return builder;
601                         }
602
603                         builder.Init (parser, this, null, prop.Name, null, atts);
604                         builder.fileName = fileName;
605                         builder.line = line;
606                         builder.isProperty = true;
607                         if (idx >= 0)
608                                 builder.originalTagName = propName;
609                         return builder;
610                 }
611                 
612                 public virtual void Init (TemplateParser parser,
613                                           ControlBuilder parentBuilder,
614                                           Type type,
615                                           string tagName,
616                                           string id,
617                                           IDictionary attribs)
618                 {
619                         this.parser = parser;
620                         if (parser != null)
621                                 this.location = parser.Location;
622
623                         this.parentBuilder = parentBuilder;
624                         this.type = type;
625                         this.tagName = tagName;
626                         this.id = id;
627                         this.attribs = attribs;
628                         if (type == null)
629                                 return;
630
631                         if (this is TemplateBuilder)
632                                 return;
633
634                         object [] atts = type.GetCustomAttributes (typeof (ParseChildrenAttribute), true);
635                         
636                         if (!typeof (IParserAccessor).IsAssignableFrom (type) && atts.Length == 0) {
637                                 isIParserAccessor = false;
638                                 childrenAsProperties = true;
639                         } else if (atts.Length > 0) {
640                                 ParseChildrenAttribute att = (ParseChildrenAttribute) atts [0];
641                                 childrenAsProperties = att.ChildrenAsProperties;
642                                 if (childrenAsProperties && att.DefaultProperty.Length != 0)
643                                         defaultPropertyBuilder = CreatePropertyBuilder (att.DefaultProperty,
644                                                                                         parser, null);
645                         }
646                 }
647
648                 public virtual bool NeedsTagInnerText ()
649                 {
650                         return false;
651                 }
652
653                 public virtual void OnAppendToParentBuilder (ControlBuilder parentBuilder)
654                 {
655                         if (defaultPropertyBuilder == null)
656                                 return;
657
658                         ControlBuilder old = defaultPropertyBuilder;
659                         defaultPropertyBuilder = null;
660                         AppendSubBuilder (old);
661                 }
662
663                 internal void SetTagName (string name)
664                 {
665                         tagName = name;
666                 }
667                 
668                 public virtual void SetTagInnerText (string text)
669                 {
670                 }
671
672                 internal string GetNextID (string proposedID)
673                 {
674                         if (proposedID != null && proposedID.Trim ().Length != 0)
675                                 return proposedID;
676
677                         return "_bctrl_" + nextID++;
678                 }
679
680                 internal virtual ControlBuilder CreateSubBuilder (string tagid,
681                                                                   Hashtable atts,
682                                                                   Type childType,
683                                                                   TemplateParser parser,
684                                                                   ILocation location)
685                 {
686                         ControlBuilder childBuilder = null;
687                         if (childrenAsProperties) {
688                                 if (defaultPropertyBuilder == null)
689                                         childBuilder = CreatePropertyBuilder (tagid, parser, atts);
690                                 else {
691                                         if (String.Compare (defaultPropertyBuilder.TagName, tagid, true, CultureInfo.InvariantCulture) == 0) {
692                                                 // The child tag is the same what our default property name. Act as if there was
693                                                 // no default property builder, or otherwise we'll end up with invalid nested
694                                                 // builder call.
695                                                 defaultPropertyBuilder = null;
696                                                 childBuilder = CreatePropertyBuilder (tagid, parser, atts);
697                                         } else
698                                                 childBuilder = defaultPropertyBuilder.CreateSubBuilder (tagid, atts,
699                                                                                                         null, parser,
700                                                                                                         location);
701                                 }
702
703                                 return childBuilder;
704                         }
705
706                         if (String.Compare (tagName, tagid, true, CultureInfo.InvariantCulture) == 0)
707                                 return null;
708                         
709                         childType = GetChildControlType (tagid, atts);
710                         if (childType == null)
711                                 return null;
712
713                         childBuilder = CreateBuilderFromType (parser, this, childType, tagid, id, atts,
714                                                               location.BeginLine, location.Filename);
715
716                         return childBuilder;
717                 }
718
719                 internal virtual object CreateInstance ()
720                 {
721                         // HtmlGenericControl, HtmlTableCell...
722                         object [] atts = type.GetCustomAttributes (typeof (ConstructorNeedsTagAttribute), true);
723                         object [] args = null;
724                         if (atts != null && atts.Length > 0) {
725                                 ConstructorNeedsTagAttribute att = (ConstructorNeedsTagAttribute) atts [0];
726                                 if (att.NeedsTag)
727                                         args = new object [] {tagName};
728                         }
729
730                         return Activator.CreateInstance (type, args);
731                 }
732
733                 internal virtual void CreateChildren (object parent) 
734                 {
735                         if (children == null || children.Count == 0)
736                                 return;
737
738                         IParserAccessor parser = parent as IParserAccessor;
739                         if (parser == null)
740                                 return;
741
742                         foreach (object o in children) {
743                                 if (o is string) {
744                                         parser.AddParsedSubObject (new LiteralControl ((string) o));
745                                 } else {
746                                         parser.AddParsedSubObject (((ControlBuilder) o).CreateInstance ());
747                                 }
748                         }
749                 }
750 #if NET_2_0
751                 [MonoTODO ("unsure, lack documentation")]
752                 public virtual object BuildObject ()
753                 {
754                         return CreateInstance ();
755                 }
756                 
757                 [MonoTODO]
758                 public virtual void ProcessGeneratedCode(CodeCompileUnit codeCompileUnit,
759                         CodeTypeDeclaration baseType,
760                         CodeTypeDeclaration derivedType,
761                         CodeMemberMethod buildMethod,
762                         CodeMemberMethod dataBindingMethod)
763                 {
764                         throw new NotImplementedException ();
765                 }
766
767                 internal void ResetState()
768                 {
769                         renderIndex = 0;
770                         haveParserVariable = false;
771
772                         if (Children != null) {
773                                 foreach (object child in Children) {
774                                         ControlBuilder cb = child as ControlBuilder;
775                                         if (cb != null)
776                                                 cb.ResetState ();
777                                 }
778                         }
779                 }
780 #endif
781         }
782 }