2004-03-04 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / Control.cs
1 //
2 // System.Web.UI.Control.cs
3 //
4 // Authors:
5 //   Bob Smith <bob@thestuff.net>
6 //   Gonzalo Paniagua Javier (gonzalo@ximian.com
7 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 //
9 // (C) Bob Smith
10 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
11 //
12
13 using System;
14 using System.Collections;
15 using System.ComponentModel;
16 using System.ComponentModel.Design;
17 using System.ComponentModel.Design.Serialization;
18 using System.Web;
19 using System.Web.Util;
20
21 namespace System.Web.UI
22 {
23         [DefaultProperty ("ID"), DesignerCategory ("Code"), ToolboxItemFilter ("System.Web.UI", ToolboxItemFilterType.Require)]
24         [ToolboxItem ("System.Web.UI.Design.WebControlToolboxItem, " + Consts.AssemblySystem_Design)]
25         [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
26         [DesignerSerializer ("Microsoft.VSDesigner.WebForms.ControlCodeDomSerializer, " + Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
27         public class Control : IComponent, IDisposable, IParserAccessor, IDataBindingsAccessor
28         {
29                 private static readonly object DataBindingEvent = new object();
30                 private static readonly object DisposedEvent = new object();
31                 private static readonly object InitEvent = new object();
32                 private static readonly object LoadEvent = new object();
33                 private static readonly object PreRenderEvent = new object();
34                 private static readonly object UnloadEvent = new object();
35                 private string uniqueID;
36                 private string _userId;
37                 private bool id_set;
38                 private string _cachedClientId;
39                 private ControlCollection _controls;
40                 private bool _enableViewState = true;
41                 private IDictionary _childViewStates; //TODO: Not sure datatype. Placeholder guess.
42                 private bool _isNamingContainer;
43                 private Control _namingContainer;
44                 private Page _page;
45                 private Control _parent;
46                 private ISite _site;
47                 private bool _visible = true;
48                 private bool visibleChanged;
49                 private HttpContext _context;
50                 private bool _childControlsCreated;
51                 private StateBag _viewState;
52                 private bool _trackViewState;
53                 private EventHandlerList _events = new EventHandlerList();
54                 private RenderMethod _renderMethodDelegate;
55                 private bool autoID = true;
56                 private bool creatingControls;
57                 private bool bindingContainer = true;
58                 private bool autoEventWireup = true;
59
60                 bool inited, initing;
61                 bool viewStateLoaded;
62                 bool loaded;
63                 bool prerendered;
64                 int defaultNumberID;
65  
66                 DataBindingCollection dataBindings;
67                 Hashtable pendingVS; // may hold unused viewstate data from child controls
68
69                 public Control()\r
70                 {\r
71                         if (this is INamingContainer) _isNamingContainer = true;\r
72                 }\r
73
74                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
75                 [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)]\r
76                 public Control BindingContainer\r
77                 {\r
78                         get {\r
79                                 Control container = NamingContainer;\r
80                                 if (!container.bindingContainer)\r
81                                         container = container.BindingContainer;\r
82                                 return container;\r
83                         }\r
84                 }\r
85                 
86                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
87                 [Browsable (false)]
88                 [WebSysDescription ("An Identification of the control that is rendered.")]\r
89                 public virtual string ClientID {\r
90                         get {\r
91                                 string client = UniqueID;\r
92 \r
93                                 if (client != null)\r
94                                         client = client.Replace (':', '_');\r
95 \r
96                                 return client;\r
97                         }\r
98                 }\r
99
100                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
101                 [Browsable (false)]
102                 [WebSysDescription ("The child controls of this control.")]\r
103                 public virtual ControlCollection Controls //DIT\r
104                 {\r
105                         get\r
106                         {\r
107                                 if (_controls == null) _controls = CreateControlCollection();\r
108                                 return _controls;\r
109                         }\r
110                 }
111
112                 [DefaultValue (true), WebCategory ("FIXME")]
113                 [WebSysDescription ("An Identification of the control that is rendered.")]\r
114                 public virtual bool EnableViewState //DIT\r
115                 {\r
116                         get\r
117                         {\r
118                                 return _enableViewState;\r
119                         }\r
120                         set\r
121                         {\r
122                                 _enableViewState = value;\r
123                         }\r
124                 }\r
125                 
126                 [MergableProperty (false), ParenthesizePropertyName (true)]
127                 [WebSysDescription ("The name of the control that is rendered.")]\r
128                 public virtual string ID {\r
129                         get {\r
130                                 return (id_set ? _userId : null);
131                         }\r
132                         \r
133                         set {\r
134                                 if (value == "")\r
135                                         value = null;\r
136 \r
137                                 id_set = true;
138                                 _userId = value;\r
139                                 NullifyUniqueID ();\r
140                         }\r
141                 }\r
142                 
143                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
144                 [Browsable (false)]
145                 [WebSysDescription ("The container that this control is part of. The control's name has to be unique within the container.")]\r
146                 public virtual Control NamingContainer //DIT\r
147                 {\r
148                         get\r
149                         {\r
150                                 if (_namingContainer == null && _parent != null)\r
151                                 {\r
152                                         if (_parent._isNamingContainer == false)\r
153                                                 _namingContainer = _parent.NamingContainer;\r
154                                         else\r
155                                                 _namingContainer = _parent;\r
156                                 }\r
157                                 return _namingContainer;\r
158                         }\r
159                 }
160
161                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
162                 [Browsable (false)]
163                 [WebSysDescription ("The webpage that this control resides on.")]\r
164                 public virtual Page Page //DIT\r
165                 {\r
166                         get\r
167                         {\r
168                                 if (_page == null && _parent != null) _page = _parent.Page;\r
169                                 return _page;\r
170                         }\r
171                         set\r
172                         {\r
173                                 _page = value;\r
174                         }\r
175                 }
176
177                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
178                 [Browsable (false)]
179                 [WebSysDescription ("The parent control of this control.")]\r
180                 public virtual Control Parent //DIT\r
181                 {\r
182                         get\r
183                         {\r
184                                 return _parent;\r
185                         }\r
186                 }
187
188                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
189                 [EditorBrowsable (EditorBrowsableState.Advanced), Browsable (false)]
190                 [WebSysDescription ("The site this control is part of.")]\r
191                 public ISite Site //DIT\r
192                 {\r
193                         get\r
194                         {\r
195                                 return _site;\r
196                         }\r
197                         set\r
198                         {\r
199                                 _site = value;\r
200                         }\r
201                 }\r
202
203                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
204                 [Browsable (false)]
205                 [WebSysDescription ("A virtual directory containing the parent of the control.")]\r
206                 public virtual string TemplateSourceDirectory {\r
207                         get { return (_parent == null) ? String.Empty : _parent.TemplateSourceDirectory; }\r
208                 }\r
209
210                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
211                 [Browsable (false)]
212                 [WebSysDescription ("The unique ID of the control.")]\r
213                 public virtual string UniqueID {\r
214                         get {\r
215                                 if (uniqueID != null)\r
216                                         return uniqueID;\r
217 \r
218                                 if (_namingContainer == null) {\r
219                                         return _userId;\r
220                                 }\r
221 \r
222                                 if (_userId == null)\r
223                                         _userId = _namingContainer.GetDefaultName ();\r
224 \r
225                                 string prefix = _namingContainer.UniqueID;\r
226                                 if (_namingContainer == _page || prefix == null) {\r
227                                         uniqueID = _userId;\r
228                                         return uniqueID;\r
229                                 }\r
230 \r
231                                 uniqueID = prefix + ":" + _userId;\r
232                                 return uniqueID;\r
233                         }\r
234                 }
235
236                 [DefaultValue (true), Bindable (true), WebCategory ("FIXME")]
237                 [WebSysDescription ("Visiblity state of the control.")]
238                 public virtual bool Visible {
239                         get {
240                                 if (_visible == false)
241                                         return false;
242
243                                 if (_parent != null)
244                                         return _parent.Visible;
245
246                                 return true;
247                         }
248
249                         set {
250                                 if (value != _visible) {
251                                         if (IsTrackingViewState)
252                                                 visibleChanged = true;
253                                 }
254
255                                 _visible = value;
256                         }
257                 }
258
259                 protected bool ChildControlsCreated //DIT\r
260                 {\r
261                         get\r
262                         {\r
263                                 return _childControlsCreated;\r
264                         }\r
265                         set\r
266                         {\r
267                                 if (value == false && _childControlsCreated == true)\r
268                                         _controls.Clear();\r
269                                 _childControlsCreated = value;\r
270                         }\r
271                 }\r
272                 protected virtual HttpContext Context //DIT\r
273                 {\r
274                         get\r
275                         {\r
276                                 HttpContext context;\r
277                                 if (_context != null)\r
278                                         return _context;\r
279                                 if (_parent == null)\r
280                                         return HttpContext.Current;\r
281                                 context = _parent.Context;\r
282                                 if (context != null)\r
283                                         return context;\r
284                                 return HttpContext.Current;\r
285                         }\r
286                 }\r
287                 protected EventHandlerList Events //DIT\r
288                 {\r
289                         get\r
290                         {\r
291                                 if (_events == null)\r
292                                 {\r
293                                         _events = new EventHandlerList();\r
294                                 }\r
295                                 return _events;\r
296                         }\r
297                 }\r
298                 protected bool HasChildViewState //DIT\r
299                 {\r
300                         get\r
301                         {\r
302                                 if (_childViewStates == null) return false;\r
303                                 return true;\r
304                         }\r
305                 }\r
306                 protected bool IsTrackingViewState //DIT\r
307                 {\r
308                         get\r
309                         {\r
310                                 return _trackViewState;\r
311                         }\r
312                 }\r
313                 protected virtual StateBag ViewState\r
314                 {\r
315                         get\r
316                         {\r
317                                 if(_viewState == null)\r
318                                         _viewState = new StateBag (ViewStateIgnoresCase);\r
319 \r
320                                 if (IsTrackingViewState)\r
321                                         _viewState.TrackViewState ();\r
322 \r
323                                 return _viewState;\r
324                         }\r
325                 }\r
326 \r
327                 protected virtual bool ViewStateIgnoresCase\r
328                 {\r
329                         get {\r
330                                 return false;\r
331                         }\r
332                 }\r
333 \r
334                 internal bool AutoEventWireup {\r
335                         get { return autoEventWireup; }\r
336                         set { autoEventWireup = value; }\r
337                 }\r
338 \r
339                 internal void SetBindingContainer (bool isBC)\r
340                 {\r
341                         bindingContainer = isBC;\r
342                 }\r
343                 \r
344                 internal void ResetChildNames ()\r
345                 {\r
346                         defaultNumberID = 0;\r
347                 }\r
348                 \r
349                 string GetDefaultName ()\r
350                 {\r
351                         return "_ctrl" + defaultNumberID++;\r
352                 }\r
353                 \r
354                 void NullifyUniqueID ()\r
355                 {\r
356                         uniqueID = null;\r
357                         if (_controls == null)\r
358                                 return;\r
359 \r
360                         foreach (Control c in _controls)\r
361                                 c.NullifyUniqueID ();\r
362                 }\r
363                 \r
364                 protected internal virtual void AddedControl (Control control, int index)\r
365                 {\r
366                         /* Ensure the control don't have more than 1 parent */
367                         if (control._parent != null)
368                                 control._parent.Controls.Remove (control);
369
370                         control._parent = this;
371                         control._page = _page;
372                         Control nc = _isNamingContainer ? this : NamingContainer;
373
374                         if (nc != null) {
375                                 control._namingContainer = nc;
376                                 if (control.AutoID == true && control._userId == null)
377                                         control._userId =  nc.GetDefaultName () + "a";
378                         }
379
380                         if (initing || inited)
381                                 control.InitRecursive (nc);
382
383                         if (viewStateLoaded || loaded) {
384                                 if (pendingVS != null) {
385                                         object vs = pendingVS [index];
386                                         if (vs != null) {
387                                                 pendingVS.Remove (index);
388                                                 if (pendingVS.Count == 0)
389                                                         pendingVS = null;
390                                         
391                                                 control.LoadViewStateRecursive (vs);
392                                         }
393                                 }
394                         }
395
396                         if (loaded)
397                                 control.LoadRecursive ();
398                         
399                         if (prerendered)
400                                 control.PreRenderRecursiveInternal ();
401                 }
402
403                 protected virtual void AddParsedSubObject(object obj) //DIT\r
404                 {\r
405                         WebTrace.PushContext ("Control.AddParsedSubobject ()");\r
406                         Control c = obj as Control;\r
407                         WebTrace.WriteLine ("Start: {0} -> {1}", obj, (c != null) ? c.ID : String.Empty);\r
408                         if (c != null) Controls.Add(c);\r
409                         WebTrace.WriteLine ("End");\r
410                         WebTrace.PopContext ();\r
411                 }\r
412
413                 protected void BuildProfileTree(string parentId, bool calcViewState)\r
414                 {\r
415                         //TODO\r
416                 }\r
417
418                 protected void ClearChildViewState ()
419                 {
420                         pendingVS = null;
421                 }
422
423                 protected virtual void CreateChildControls() {} //DIT\r
424                 protected virtual ControlCollection CreateControlCollection() //DIT\r
425                 {\r
426                         return new ControlCollection(this);\r
427                 }\r
428 \r
429                 protected virtual void EnsureChildControls () //DIT\r
430                 {\r
431                         if (ChildControlsCreated == false && !creatingControls) {\r
432                                 creatingControls = true;\r
433                                 CreateChildControls();\r
434                                 ChildControlsCreated = true;\r
435                                 creatingControls = false;\r
436                         }\r
437                 }
438
439                 protected bool IsLiteralContent()
440                 {
441                         if (_controls != null) 
442                                 if (_controls.Count == 1)
443                                         if (_controls[0] is LiteralControl)
444                                                 return true;
445                         return false;
446                 }\r
447 \r
448                 public virtual Control FindControl (string id)\r
449                 {\r
450                         return FindControl (id, 0);\r
451                 }\r
452 \r
453                 Control LookForControlByName (string id)\r
454                 {\r
455                         if (!HasChildren)\r
456                                 return null;\r
457 \r
458                         foreach (Control c in _controls) {\r
459                                 if (String.Compare (id, c._userId, true) == 0)\r
460                                         return c;\r
461 \r
462                                 if (!c._isNamingContainer && c.HasChildren) {\r
463                                         Control child = c.LookForControlByName (id);\r
464                                         if (child != null)\r
465                                                 return child;\r
466                                 }\r
467                         }\r
468 \r
469                         return null;\r
470                 }\r
471                 \r
472                 protected virtual Control FindControl (string id, int pathOffset)\r
473                 {\r
474                         EnsureChildControls ();\r
475                         if (_controls == null)\r
476                                 return null;\r
477 \r
478                         Control namingContainer = null;\r
479                         if (!_isNamingContainer) {\r
480                                 namingContainer = NamingContainer;\r
481                                 if (namingContainer == null)\r
482                                         return null;\r
483 \r
484                                 return namingContainer.FindControl (id, pathOffset);\r
485                         }\r
486 \r
487                         int colon = id.IndexOf (':', pathOffset);\r
488                         if (colon == -1)\r
489                                 return LookForControlByName (id.Substring (pathOffset));\r
490                         \r
491                         string idfound = id.Substring (pathOffset, colon - pathOffset);\r
492                         namingContainer = LookForControlByName (idfound);\r
493                         if (namingContainer == null)\r
494                                 return null;\r
495 \r
496                         return namingContainer.FindControl (id, colon + 1);\r
497                 }
498
499                 protected virtual void LoadViewState(object savedState)
500                 {
501                         if (savedState != null) {
502                                 ViewState.LoadViewState (savedState);
503                                 object o = ViewState ["Visible"];
504                                 if (o != null) {
505                                         _visible = (bool) o;
506                                         visibleChanged = true;
507                                 }
508                         }
509                 }
510
511                 [MonoTODO("Secure?")]\r
512                 protected string MapPathSecure(string virtualPath)\r
513                 {\r
514                         string combined = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);\r
515                         return Context.Request.MapPath (combined);\r
516                 }\r
517 \r
518                 protected virtual bool OnBubbleEvent(object source, EventArgs args) //DIT\r
519                 {\r
520                         return false;\r
521                 }\r
522                 protected virtual void OnDataBinding(EventArgs e) //DIT\r
523                 {\r
524                         if (_events != null)\r
525                         {\r
526                                 EventHandler eh = (EventHandler)(_events[DataBindingEvent]);\r
527                                 if (eh != null) eh(this, e);\r
528                         }\r
529                 }\r
530                 protected virtual void OnInit(EventArgs e) //DIT\r
531                 {\r
532                         if (_events != null)\r
533                         {\r
534                                 EventHandler eh = (EventHandler)(_events[InitEvent]);\r
535                                 if (eh != null) eh(this, e);\r
536                         }\r
537                 }\r
538                 protected virtual void OnLoad(EventArgs e) //DIT\r
539                 {\r
540                         if (_events != null)\r
541                         {\r
542                                 EventHandler eh = (EventHandler)(_events[LoadEvent]);\r
543                                 if (eh != null) eh(this, e);\r
544                         }\r
545                 }\r
546                 protected virtual void OnPreRender(EventArgs e) //DIT\r
547                 {\r
548                         if (_events != null)\r
549                         {\r
550                                 EventHandler eh = (EventHandler)(_events[PreRenderEvent]);\r
551                                 if (eh != null) eh(this, e);\r
552                         }\r
553                 }\r
554                 protected virtual void OnUnload(EventArgs e) //DIT\r
555                 {\r
556                         if (_events != null)\r
557                         {\r
558                                 EventHandler eh = (EventHandler)(_events[UnloadEvent]);\r
559                                 if (eh != null) eh(this, e);\r
560                         }\r
561                 }\r
562                 \r
563                 protected void RaiseBubbleEvent(object source, EventArgs args)\r
564                 {\r
565                         Control c = Parent;\r
566                         while (c != null) {\r
567                                 if (c.OnBubbleEvent (source, args))\r
568                                         break;\r
569                                 c = c.Parent;\r
570                         }\r
571                 }\r
572 \r
573                 protected virtual void Render(HtmlTextWriter writer) //DIT\r
574                 {\r
575                         RenderChildren(writer);\r
576                 }\r
577 \r
578                 protected virtual void RenderChildren(HtmlTextWriter writer) //DIT\r
579                 {\r
580                         if (_renderMethodDelegate != null)\r
581                                 _renderMethodDelegate(writer, this);\r
582                         else if (_controls != null)\r
583                                 foreach (Control c in _controls)\r
584                                         c.RenderControl(writer);\r
585                 }\r
586
587                 protected virtual object SaveViewState ()
588                 {
589                         if (visibleChanged) {
590                                 ViewState ["Visible"] = Visible;
591                         } else if (_viewState == null) {
592                                 return null;
593                         }
594
595                         return _viewState.SaveViewState ();
596                 }
597
598                 protected virtual void TrackViewState()\r
599                 {\r
600                         if (_viewState != null)\r
601                                 _viewState.TrackViewState ();\r
602                         _trackViewState = true;\r
603                 }\r
604                 \r
605                 public virtual void Dispose()\r
606                 {\r
607                         if (_events != null)\r
608                         {\r
609                                 EventHandler eh = (EventHandler) _events [DisposedEvent];\r
610                                 if (eh != null)\r
611                                         eh(this, EventArgs.Empty);\r
612                         }\r
613                 }\r
614 \r
615                 internal bool HasChildren\r
616                 {\r
617                         get { return (_controls != null && _controls.Count > 0); }\r
618                 }\r
619
620                 [WebCategory ("FIXME")]
621                 [WebSysDescription ("Raised when the contols databound properties are evaluated.")]\r
622                 public event EventHandler DataBinding //DIT\r
623                 {\r
624                         add\r
625                         {\r
626                                 Events.AddHandler(DataBindingEvent, value);\r
627                         }\r
628                         remove\r
629                         {\r
630                                 Events.RemoveHandler(DataBindingEvent, value);\r
631                         }\r
632                 }
633
634                 [WebSysDescription ("Raised when the contol is disposed.")]\r
635                 public event EventHandler Disposed //DIT\r
636                 {\r
637                         add\r
638                         {\r
639                                 Events.AddHandler(DisposedEvent, value);\r
640                         }\r
641                         remove\r
642                         {\r
643                                 Events.RemoveHandler(DisposedEvent, value);\r
644                         }\r
645                 }
646
647                 [WebSysDescription ("Raised when the page containing the control is initialized.")]\r
648                 public event EventHandler Init //DIT\r
649                 {\r
650                         add\r
651                         {\r
652                                 Events.AddHandler(InitEvent, value);\r
653                         }\r
654                         remove\r
655                         {\r
656                                 Events.RemoveHandler(InitEvent, value);\r
657                         }\r
658                 }
659
660                 [WebSysDescription ("Raised after the page containing the control has been loaded.")]\r
661                 public event EventHandler Load //DIT\r
662                 {\r
663                         add\r
664                         {\r
665                                 Events.AddHandler(LoadEvent, value);\r
666                         }\r
667                         remove\r
668                         {\r
669                                 Events.RemoveHandler(LoadEvent, value);\r
670                         }\r
671                 }
672
673                 [WebSysDescription ("Raised before the page containing the control is rendered.")]\r
674                 public event EventHandler PreRender //DIT\r
675                 {\r
676                         add\r
677                         {\r
678                                 Events.AddHandler(PreRenderEvent, value);\r
679                         }\r
680                         remove\r
681                         {\r
682                                 Events.RemoveHandler(PreRenderEvent, value);\r
683                         }\r
684                 }
685
686                 [WebSysDescription ("Raised when the page containing the control is unloaded.")]\r
687                 public event EventHandler Unload //DIT\r
688                 {\r
689                         add\r
690                         {\r
691                                 Events.AddHandler(UnloadEvent, value);\r
692                         }\r
693                         remove\r
694                         {\r
695                                 Events.RemoveHandler(UnloadEvent, value);\r
696                         }\r
697                 }\r
698 \r
699                 public virtual void DataBind() //DIT\r
700                 {
701                         #if NET_1_2
702                         bool foundDataItem = false;
703                         
704                         if (_isNamingContainer && Page != null) {
705                                 object o = DataBinder.GetDataItem (this, out foundDataItem);
706                                 if (foundDataItem)
707                                         Page.PushDataItemContext (o);
708                         }
709                         
710                         try {
711                         #endif
712                                 
713                                 OnDataBinding (EventArgs.Empty);
714                                 DataBindChildren();
715                         
716                         #if NET_1_2
717                         } finally {
718                                 if (foundDataItem)
719                                         Page.PopDataItemContext ();
720                         }
721                         #endif
722                 }
723                 
724                 #if NET_1_2
725                 protected virtual
726                 #endif
727                 
728                 void DataBindChildren ()
729                 {
730                         if (_controls == null)
731                                 return;
732                         
733                         foreach (Control c in _controls)
734                                 c.DataBind();
735                 }
736                 \r
737 \r
738                 public virtual bool HasControls() //DIT\r
739                 {\r
740                         if (_controls != null && _controls.Count >0) return true;\r
741                         return false;\r
742                 }\r
743
744                 public void RenderControl(HtmlTextWriter writer)
745                 {
746                         if (_visible)
747                                 Render(writer);
748                 }
749
750                 public string ResolveUrl(string relativeUrl)\r
751                 {\r
752                         if (relativeUrl == null)\r
753                                 throw new ArgumentNullException ("relativeUrl");\r
754 \r
755                         if (relativeUrl == "")\r
756                                 return "";\r
757 \r
758                         if (relativeUrl [0] == '#')
759                                 return relativeUrl;
760                         
761                         string ts = TemplateSourceDirectory;\r
762                         if (UrlUtils.IsRelativeUrl (relativeUrl) == false || ts == "")\r
763                                 return relativeUrl;\r
764                         \r
765                         HttpResponse resp = Context.Response;\r
766                         return resp.ApplyAppPathModifier (UrlUtils.Combine (ts, relativeUrl));\r
767                 }
768
769                 [EditorBrowsable (EditorBrowsableState.Advanced)]\r
770                 public void SetRenderMethodDelegate(RenderMethod renderMethod) //DIT\r
771                 {\r
772                         _renderMethodDelegate = renderMethod;\r
773                 }\r
774 \r
775                 internal void LoadRecursive()\r
776                 {\r
777                         OnLoad (EventArgs.Empty);\r
778                         if (_controls != null) {\r
779                                 foreach (Control c in _controls)\r
780                                         c.LoadRecursive ();\r
781                         }\r
782                         loaded = true;\r
783                 }\r
784 \r
785                 internal void UnloadRecursive(Boolean dispose)\r
786                 {\r
787                         if (_controls != null) {\r
788                                 foreach (Control c in _controls)\r
789                                         c.UnloadRecursive (dispose);\r
790                         }\r
791 \r
792                         OnUnload (EventArgs.Empty);\r
793                         if (dispose)\r
794                                 Dispose();\r
795                 }\r
796
797                 internal void PreRenderRecursiveInternal()
798                 {
799                         if (_visible) {
800                                 EnsureChildControls ();
801                                 OnPreRender (EventArgs.Empty);
802                                 if (_controls == null)
803                                         return;
804
805                                 foreach (Control c in _controls)
806                                         c.PreRenderRecursiveInternal ();
807                         }
808                         prerendered = true;
809                 }
810
811                 internal void InitRecursive(Control namingContainer)\r
812                 {\r
813                         if (_controls != null) {\r
814                                 if (_isNamingContainer)\r
815                                         namingContainer = this;\r
816 \r
817                                 if (namingContainer != null && \r
818                                     namingContainer._userId == null &&\r
819                                     namingContainer.autoID)\r
820                                         namingContainer._userId = namingContainer.GetDefaultName () + "b";\r
821 \r
822                                 foreach (Control c in _controls) {\r
823                                         c._page = Page;\r
824                                         c._namingContainer = namingContainer;\r
825                                         if (namingContainer != null && c._userId == null && c.autoID)\r
826                                                 c._userId = namingContainer.GetDefaultName () + "c";\r
827 \r
828                                         c.InitRecursive (namingContainer);\r
829                                 }\r
830                         }\r
831 \r
832                         initing = true;
833                         OnInit (EventArgs.Empty);\r
834                         TrackViewState ();\r
835                         inited = true;\r
836                         initing = false;
837                 }\r
838
839                 internal object SaveViewStateRecursive ()
840                 {
841                         if (!EnableViewState)
842                                 return null;
843
844                         ArrayList controlList = null;
845                         ArrayList controlStates = null;
846
847                         int idx = -1;
848                         foreach (Control ctrl in Controls) {
849                                 object ctrlState = ctrl.SaveViewStateRecursive ();
850                                 idx++;
851                                 if (ctrlState == null)
852                                         continue;
853
854                                 if (controlList == null) {
855                                         controlList = new ArrayList ();
856                                         controlStates = new ArrayList ();
857                                 }
858
859                                 controlList.Add (idx);
860                                 controlStates.Add (ctrlState);
861                         }
862
863                         object thisState = SaveViewState ();
864                         if (thisState == null && controlList == null && controlStates == null)
865                                 return null;
866
867                         return new Triplet (thisState, controlList, controlStates);
868                 }
869                 
870                 internal void LoadViewStateRecursive (object savedState)
871                 {
872                         if (!EnableViewState || savedState == null)
873                                 return;
874
875                         Triplet savedInfo = (Triplet) savedState;
876                         LoadViewState (savedInfo.First);
877
878                         ArrayList controlList = savedInfo.Second as ArrayList;
879                         if (controlList == null)
880                                 return;
881                         ArrayList controlStates = savedInfo.Third as ArrayList;
882                         int nControls = controlList.Count;
883                         for (int i = 0; i < nControls; i++) {
884                                 int k = (int) controlList [i];
885                                 if (k < Controls.Count && controlStates != null) {
886                                         Control c = Controls [k];
887                                         c.LoadViewStateRecursive (controlStates [i]);
888                                 } else {
889                                         if (pendingVS == null)
890                                                 pendingVS = new Hashtable ();
891
892                                         pendingVS [k] = controlStates [i];
893                                 }
894                         }
895
896                         viewStateLoaded = true;
897                 }
898                 
899                 void IParserAccessor.AddParsedSubObject(object obj)\r
900                 {\r
901                         AddParsedSubObject(obj);\r
902                 }\r
903                 \r
904                 DataBindingCollection IDataBindingsAccessor.DataBindings\r
905                 {\r
906                         get\r
907                         {\r
908                                 if(dataBindings == null)\r
909                                         dataBindings = new DataBindingCollection();\r
910                                 return dataBindings;\r
911                         }\r
912                 }\r
913                 \r
914                 bool IDataBindingsAccessor.HasDataBindings\r
915                 {\r
916                         get\r
917                         {\r
918                                 return (dataBindings!=null && dataBindings.Count>0);\r
919                         }\r
920                 }\r
921                 \r
922                 internal bool AutoID\r
923                 {\r
924                         get { return autoID; }\r
925                         set { \r
926                                 if (value == false && _isNamingContainer)\r
927                                         return;\r
928 \r
929                                 autoID = value;\r
930                         }\r
931                 }\r
932 \r
933                 internal void PreventAutoID()\r
934                 {\r
935                         AutoID = false;\r
936                 }\r
937                 \r
938                 protected internal virtual void RemovedControl (Control control)\r
939                 {\r
940                         control.UnloadRecursive (false);\r
941                         control._parent = null;\r
942                         control._page = null;\r
943                         control._namingContainer = null;\r
944                 }\r
945 \r
946                 //TODO: I think there are some needed Interface implementations to do here.
947                 
948                 #if NET_1_2
949                 protected string GetWebResourceUrl (string resourceName)
950                 {
951                         return Page.GetWebResourceUrl (GetType(), resourceName); 
952                 } 
953
954                 #endif\r
955         }\r
956 }\r