2005-04-21 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 //   Sanjay Gupta (gsanjay@novell.com)
9 //
10 // (C) Bob Smith
11 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
12 // (C) 2004 Novell, Inc. (http://www.novell.com)
13 //
14
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System;
37 using System.Collections;
38 using System.ComponentModel;
39 using System.ComponentModel.Design;
40 using System.ComponentModel.Design.Serialization;
41 using System.Web;
42 using System.Web.Util;
43
44 namespace System.Web.UI
45 {
46         [DefaultProperty ("ID"), DesignerCategory ("Code"), ToolboxItemFilter ("System.Web.UI", ToolboxItemFilterType.Require)]
47         [ToolboxItem ("System.Web.UI.Design.WebControlToolboxItem, " + Consts.AssemblySystem_Design)]
48         [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
49         [DesignerSerializer ("Microsoft.VSDesigner.WebForms.ControlCodeDomSerializer, " + Consts.AssemblyMicrosoft_VSDesigner,
50                                 "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
51         public class Control : IComponent, IDisposable, IParserAccessor, IDataBindingsAccessor
52 #if NET_2_0
53         , IUrlResolutionService, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
54 #endif
55         {
56                 static readonly object DataBindingEvent = new object();
57                 static readonly object DisposedEvent = new object();
58                 static readonly object InitEvent = new object();
59                 static readonly object LoadEvent = new object();
60                 static readonly object PreRenderEvent = new object();
61                 static readonly object UnloadEvent = new object();
62                 static string[] defaultNameArray;
63
64                 string uniqueID;
65                 string _userId;
66                 ControlCollection _controls;
67                 IDictionary _childViewStates;
68                 Control _namingContainer;
69                 Page _page;
70                 Control _parent;
71                 ISite _site;
72                 HttpContext _context;
73                 StateBag _viewState;
74                 EventHandlerList _events;
75                 RenderMethod _renderMethodDelegate;
76                 int defaultNumberID;
77  
78                 DataBindingCollection dataBindings;
79                 Hashtable pendingVS; // may hold unused viewstate data from child controls
80                 
81
82                 /*************/
83                 int stateMask;
84                 const int ENABLE_VIEWSTATE      = 1;
85                 const int VISIBLE               = 1 << 1;
86                 const int AUTOID                = 1 << 2;
87                 const int CREATING_CONTROLS     = 1 << 3;
88                 const int BINDING_CONTAINER     = 1 << 4;
89                 const int AUTO_EVENT_WIREUP     = 1 << 5;
90                 const int IS_NAMING_CONTAINER   = 1 << 6;
91                 const int VISIBLE_CHANGED       = 1 << 7;
92                 const int TRACK_VIEWSTATE       = 1 << 8;
93                 const int CHILD_CONTROLS_CREATED = 1 << 9;
94                 const int ID_SET                = 1 << 10;
95                 const int INITED                = 1 << 11;
96                 const int INITING               = 1 << 12;
97                 const int VIEWSTATE_LOADED      = 1 << 13;
98                 const int LOADED                = 1 << 14;
99                 const int PRERENDERED           = 1 << 15;
100                 /*************/
101                 
102                 static Control ()
103                 {
104                         defaultNameArray = new string [100];
105                         for (int i = 0 ; i < 100 ; i++)
106                                 defaultNameArray [i] = "_ctrl" + i;
107                 }
108
109                 public Control()
110                 {
111                         stateMask = ENABLE_VIEWSTATE | VISIBLE | AUTOID | BINDING_CONTAINER | AUTO_EVENT_WIREUP;
112                         if (this is INamingContainer)
113                                 stateMask |= IS_NAMING_CONTAINER;
114                 }
115
116                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
117                 [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)]\r
118                 public Control BindingContainer {
119                         get {
120                                 Control container = NamingContainer;
121                                 if ((container.stateMask & BINDING_CONTAINER) == 0)
122                                         container = container.BindingContainer;
123                                 return container;
124                         }
125                 }
126
127                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
128                 [Browsable (false)]
129                 [WebSysDescription ("An Identification of the control that is rendered.")]\r
130                 public virtual string ClientID {\r
131                         get {\r
132                                 string client = UniqueID;\r
133 \r
134                                 if (client != null)\r
135                                         client = client.Replace (':', '_');\r
136 \r
137                                 return client;\r
138                         }\r
139                 }\r
140
141                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
142                 [Browsable (false)]
143                 [WebSysDescription ("The child controls of this control.")]\r
144                 public virtual ControlCollection Controls //DIT\r
145                 {\r
146                         get\r
147                         {\r
148                                 if (_controls == null) _controls = CreateControlCollection();\r
149                                 return _controls;\r
150                         }\r
151                 }
152
153                 [DefaultValue (true), WebCategory ("Behavior")]
154                 [WebSysDescription ("An Identification of the control that is rendered.")]\r
155 #if NET_2_0
156                 [Themeable (true)]
157 #endif                
158                 public virtual bool EnableViewState {
159                         get { return ((stateMask & ENABLE_VIEWSTATE) != 0); }
160                         set { SetMask (ENABLE_VIEWSTATE, value); }
161                 }
162                 
163                 [MergableProperty (false), ParenthesizePropertyName (true)]
164                 [WebSysDescription ("The name of the control that is rendered.")]\r
165 #if NET_2_0
166                 [Filterable (true), Themeable (true)]
167 #endif                
168
169                 public virtual string ID {\r
170                         get {\r
171                                 return (((stateMask & ID_SET) != 0) ? _userId : null);
172                         }\r
173                         \r
174                         set {\r
175                                 if (value == "")\r
176                                         value = null;\r
177 \r
178                                 stateMask |= ID_SET;
179                                 _userId = value;\r
180                                 NullifyUniqueID ();\r
181                         }\r
182                 }\r
183                 
184                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
185                 [Browsable (false)]
186                 [WebSysDescription ("The container that this control is part of. The control's name has to be unique within the container.")]\r
187                 public virtual Control NamingContainer {
188                         get {
189                                 if (_namingContainer == null && _parent != null) {
190                                         if ((_parent.stateMask & IS_NAMING_CONTAINER) == 0)
191                                                 _namingContainer = _parent.NamingContainer;
192                                         else
193                                                 _namingContainer = _parent;
194                                 }
195
196                                 return _namingContainer;
197                         }\r
198                 }
199
200                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
201                 [Browsable (false)]
202                 [WebSysDescription ("The webpage that this control resides on.")]\r
203 #if NET_2_0
204                 [Bindable (true)]
205 #endif                
206                 public virtual Page Page //DIT\r
207                 {\r
208                         get\r
209                         {\r
210                                 if (_page == null && _parent != null) _page = _parent.Page;\r
211                                 return _page;\r
212                         }\r
213                         set\r
214                         {\r
215                                 _page = value;\r
216                         }\r
217                 }
218
219                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
220                 [Browsable (false)]
221                 [WebSysDescription ("The parent control of this control.")]\r
222                 public virtual Control Parent //DIT\r
223                 {\r
224                         get\r
225                         {\r
226                                 return _parent;\r
227                         }\r
228                 }
229
230                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
231                 [EditorBrowsable (EditorBrowsableState.Advanced), Browsable (false)]
232                 [WebSysDescription ("The site this control is part of.")]\r
233                 public ISite Site //DIT\r
234                 {\r
235                         get\r
236                         {\r
237                                 return _site;\r
238                         }\r
239                         set\r
240                         {\r
241                                 _site = value;\r
242                         }\r
243                 }\r
244
245                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
246                 [Browsable (false)]
247                 [WebSysDescription ("A virtual directory containing the parent of the control.")]
248                 public virtual string TemplateSourceDirectory {
249                         get { return (_parent == null) ? String.Empty : _parent.TemplateSourceDirectory; }
250                 }
251
252                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
253                 [Browsable (false)]
254                 [WebSysDescription ("The unique ID of the control.")]\r
255                 public virtual string UniqueID {\r
256                         get {\r
257                                 if (uniqueID != null)\r
258                                         return uniqueID;\r
259 \r
260                                 if (_namingContainer == null) {\r
261                                         return _userId;\r
262                                 }\r
263 \r
264                                 if (_userId == null)\r
265                                         _userId = _namingContainer.GetDefaultName ();\r
266 \r
267                                 string prefix = _namingContainer.UniqueID;\r
268                                 if (_namingContainer == _page || prefix == null) {\r
269                                         uniqueID = _userId;\r
270                                         return uniqueID;\r
271                                 }\r
272 \r
273                                 uniqueID = prefix + ":" + _userId;\r
274                                 return uniqueID;\r
275                         }\r
276                 }
277
278                 void SetMask (int m, bool val)
279                 {
280                         if (val)
281                                 stateMask |= m;
282                         else
283                                 stateMask &= ~m;
284                 }
285                 
286                 [DefaultValue (true), Bindable (true), WebCategory ("Behavior")]
287                 [WebSysDescription ("Visiblity state of the control.")]
288 #if NET_2_0
289                 [Localizable (true)]            
290 #endif
291                 public virtual bool Visible {
292                         get {
293                                 if ((stateMask & VISIBLE) == 0)
294                                         return false;
295
296                                 if (_parent != null)
297                                         return _parent.Visible;
298
299                                 return true;
300                         }
301
302                         set {
303                                 if ((value && (stateMask & VISIBLE) == 0) ||
304                                     (!value && (stateMask & VISIBLE) != 0)) {
305                                         if (IsTrackingViewState)
306                                                 stateMask |= VISIBLE_CHANGED;
307                                 }
308
309                                 SetMask (VISIBLE, value);
310                         }
311                 }
312
313                 protected bool ChildControlsCreated {
314                         get { return ((stateMask & CHILD_CONTROLS_CREATED) != 0); }
315                         set {
316                                 if (value == false && (stateMask & CHILD_CONTROLS_CREATED) != 0)
317                                         Controls.Clear();
318
319                                 SetMask (CHILD_CONTROLS_CREATED, value);
320                         }
321                 }
322
323                 [Browsable (false)]
324                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
325                 protected virtual HttpContext Context //DIT\r
326                 {\r
327                         get\r
328                         {\r
329                                 HttpContext context;\r
330                                 if (_context != null)\r
331                                         return _context;\r
332                                 if (_parent == null)\r
333                                         return HttpContext.Current;\r
334                                 context = _parent.Context;\r
335                                 if (context != null)\r
336                                         return context;\r
337                                 return HttpContext.Current;\r
338                         }\r
339                 }\r
340                 protected EventHandlerList Events //DIT\r
341                 {\r
342                         get\r
343                         {\r
344                                 if (_events == null)\r
345                                 {\r
346                                         _events = new EventHandlerList();\r
347                                 }\r
348                                 return _events;\r
349                         }\r
350                 }\r
351                 protected bool HasChildViewState //DIT\r
352                 {\r
353                         get\r
354                         {\r
355                                 if (_childViewStates == null) return false;\r
356                                 return true;\r
357                         }\r
358                 }\r
359
360                 protected bool IsTrackingViewState {\r
361                         get { return ((stateMask & TRACK_VIEWSTATE) != 0); }
362                 }
363
364                 [Browsable (false)]
365                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
366                 [WebSysDescription ("ViewState")]
367                 protected virtual StateBag ViewState\r
368                 {\r
369                         get\r
370                         {\r
371                                 if(_viewState == null)\r
372                                         _viewState = new StateBag (ViewStateIgnoresCase);\r
373 \r
374                                 if (IsTrackingViewState)\r
375                                         _viewState.TrackViewState ();\r
376 \r
377                                 return _viewState;\r
378                         }\r
379                 }\r
380 \r
381                 [Browsable (false)]
382                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
383                 protected virtual bool ViewStateIgnoresCase\r
384                 {\r
385                         get {\r
386                                 return false;\r
387                         }\r
388                 }\r
389 \r
390                 internal bool AutoEventWireup {
391                         get { return (stateMask & AUTO_EVENT_WIREUP) != 0; }
392                         set { SetMask (AUTO_EVENT_WIREUP, value); }
393                 }
394
395                 internal void SetBindingContainer (bool isBC)
396                 {
397                         SetMask (BINDING_CONTAINER, isBC);
398                 }
399
400                 internal void ResetChildNames ()\r
401                 {\r
402                         defaultNumberID = 0;\r
403                 }\r
404
405                 string GetDefaultName ()
406                 {
407                         string defaultName;
408                         if (defaultNumberID > 99) {
409                                 defaultName = "_ctrl" + defaultNumberID++;
410                         } else {
411                                 defaultName = defaultNameArray [defaultNumberID++];
412                         }
413                         return defaultName;
414                 }
415
416                 void NullifyUniqueID ()\r
417                 {\r
418                         uniqueID = null;\r
419                         if (!HasControls ())\r
420                                 return;\r
421 \r
422                         foreach (Control c in Controls)
423                                 c.NullifyUniqueID ();
424                 }
425
426                 protected internal virtual void AddedControl (Control control, int index)\r
427                 {\r
428                         /* Ensure the control don't have more than 1 parent */
429                         if (control._parent != null)
430                                 control._parent.Controls.Remove (control);
431
432                         control._parent = this;
433                         control._page = _page;
434                         Control nc = ((stateMask & IS_NAMING_CONTAINER) != 0) ? this : NamingContainer;
435
436                         if (nc != null) {
437                                 control._namingContainer = nc;
438                                 if (control.AutoID == true && control._userId == null)
439                                         control._userId =  nc.GetDefaultName () + "a";
440                         }
441
442                         if ((stateMask & (INITING | INITED)) != 0)
443                                 control.InitRecursive (nc);
444
445                         if ((stateMask & (VIEWSTATE_LOADED | LOADED)) != 0) {
446                                 if (pendingVS != null) {
447                                         object vs = pendingVS [index];
448                                         if (vs != null) {
449                                                 pendingVS.Remove (index);
450                                                 if (pendingVS.Count == 0)
451                                                         pendingVS = null;
452                                         
453                                                 control.LoadViewStateRecursive (vs);
454                                         }
455                                 }
456                         }
457
458                         if ((stateMask & LOADED) != 0)
459                                 control.LoadRecursive ();
460                         
461                         if ((stateMask & PRERENDERED) != 0)
462                                 control.PreRenderRecursiveInternal ();
463                 }
464
465                 protected virtual void AddParsedSubObject(object obj) //DIT\r
466                 {\r
467                         WebTrace.PushContext ("Control.AddParsedSubobject ()");\r
468                         Control c = obj as Control;\r
469                         WebTrace.WriteLine ("Start: {0} -> {1}", obj, (c != null) ? c.ID : String.Empty);\r
470                         if (c != null) Controls.Add(c);\r
471                         WebTrace.WriteLine ("End");\r
472                         WebTrace.PopContext ();\r
473                 }\r
474
475                 protected void BuildProfileTree(string parentId, bool calcViewState)\r
476                 {\r
477                         //TODO\r
478                 }\r
479
480                 protected void ClearChildViewState ()
481                 {
482                         pendingVS = null;
483                 }
484
485                 protected virtual void CreateChildControls() {} //DIT\r
486                 protected virtual ControlCollection CreateControlCollection() //DIT\r
487                 {\r
488                         return new ControlCollection(this);\r
489                 }\r
490 \r
491                 protected virtual void EnsureChildControls ()
492                 {
493                         if (ChildControlsCreated == false && (stateMask & CREATING_CONTROLS) == 0) {
494                                 stateMask |= CREATING_CONTROLS;
495                                 CreateChildControls();
496                                 ChildControlsCreated = true;
497                                 stateMask &= ~CREATING_CONTROLS;
498                         }
499                 }
500
501                 protected bool IsLiteralContent()
502                 {
503                         if (HasControls () && Controls.Count == 1 && (Controls [0] is LiteralControl))
504                                 return true;
505
506                         return false;
507                 }
508
509                 public virtual Control FindControl (string id)\r
510                 {\r
511                         return FindControl (id, 0);\r
512                 }\r
513
514                 Control LookForControlByName (string id)
515                 {
516                         if (!HasControls ())
517                                 return null;
518
519                         Control result = null;
520                         foreach (Control c in Controls) {
521                                 if (String.Compare (id, c._userId, true) == 0) {
522                                         if (result != null && result != c) {
523                                                 throw new HttpException ("1 Found more than one control with ID '" + id + "'");
524                                         }
525
526                                         result = c;
527                                         continue;
528                                 }
529
530                                 if ((c.stateMask & IS_NAMING_CONTAINER) == 0 && c.HasControls ()) {
531                                         Control child = c.LookForControlByName (id);
532                                         if (child != null) {
533                                                 if (result != null && result != child)
534                                                         throw new HttpException ("2 Found more than one control with ID '" + id + "'");
535
536                                                 result = child;
537                                         }
538                                 }
539                         }
540
541                         return result;
542                 }
543
544                 protected virtual Control FindControl (string id, int pathOffset)\r
545                 {\r
546                         EnsureChildControls ();\r
547                         Control namingContainer = null;\r
548                         if ((stateMask & IS_NAMING_CONTAINER) == 0) {
549                                 namingContainer = NamingContainer;\r
550                                 if (namingContainer == null)\r
551                                         return null;\r
552 \r
553                                 return namingContainer.FindControl (id, pathOffset);\r
554                         }\r
555
556                         if (!HasControls ())
557                                 return null;
558
559                         int colon = id.IndexOf (':', pathOffset);\r
560                         if (colon == -1)\r
561                                 return LookForControlByName (id.Substring (pathOffset));\r
562                         \r
563                         string idfound = id.Substring (pathOffset, colon - pathOffset);\r
564                         namingContainer = LookForControlByName (idfound);\r
565                         if (namingContainer == null)\r
566                                 return null;\r
567 \r
568                         return namingContainer.FindControl (id, colon + 1);\r
569                 }
570
571                 protected virtual void LoadViewState(object savedState)
572                 {
573                         if (savedState != null) {
574                                 ViewState.LoadViewState (savedState);
575                                 object o = ViewState ["Visible"];
576                                 if (o != null) {
577                                         SetMask (VISIBLE, (bool) o);
578                                         stateMask |= VISIBLE_CHANGED;
579                                 }
580                         }
581                 }
582
583                 [MonoTODO("Secure?")]\r
584                 protected string MapPathSecure(string virtualPath)\r
585                 {\r
586                         string combined = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);\r
587                         return Context.Request.MapPath (combined);\r
588                 }\r
589 \r
590                 protected virtual bool OnBubbleEvent(object source, EventArgs args) //DIT\r
591                 {\r
592                         return false;\r
593                 }\r
594                 protected virtual void OnDataBinding(EventArgs e) //DIT\r
595                 {\r
596                         if (_events != null)\r
597                         {\r
598                                 EventHandler eh = (EventHandler)(_events[DataBindingEvent]);\r
599                                 if (eh != null) eh(this, e);\r
600                         }\r
601                 }\r
602                 protected virtual void OnInit(EventArgs e) //DIT\r
603                 {\r
604                         if (_events != null)\r
605                         {\r
606                                 EventHandler eh = (EventHandler)(_events[InitEvent]);\r
607                                 if (eh != null) eh(this, e);\r
608                         }\r
609                 }\r
610                 protected virtual void OnLoad(EventArgs e) //DIT\r
611                 {\r
612                         if (_events != null)\r
613                         {\r
614                                 EventHandler eh = (EventHandler)(_events[LoadEvent]);\r
615                                 if (eh != null) eh(this, e);\r
616                         }\r
617                 }\r
618                 protected virtual void OnPreRender(EventArgs e) //DIT\r
619                 {\r
620                         if (_events != null)\r
621                         {\r
622                                 EventHandler eh = (EventHandler)(_events[PreRenderEvent]);\r
623                                 if (eh != null) eh(this, e);\r
624                         }\r
625                 }\r
626                 protected virtual void OnUnload(EventArgs e) //DIT\r
627                 {\r
628                         if (_events != null)\r
629                         {\r
630                                 EventHandler eh = (EventHandler)(_events[UnloadEvent]);\r
631                                 if (eh != null) eh(this, e);\r
632                         }\r
633                 }\r
634                 \r
635                 protected void RaiseBubbleEvent(object source, EventArgs args)\r
636                 {\r
637                         Control c = Parent;\r
638                         while (c != null) {\r
639                                 if (c.OnBubbleEvent (source, args))\r
640                                         break;\r
641                                 c = c.Parent;\r
642                         }\r
643                 }\r
644 \r
645                 protected virtual void Render(HtmlTextWriter writer) //DIT\r
646                 {\r
647                         RenderChildren(writer);\r
648                 }\r
649
650                 protected virtual void RenderChildren (HtmlTextWriter writer) //DIT
651                 {
652                         if (_renderMethodDelegate != null) {
653                                 _renderMethodDelegate (writer, this);
654                         } else if (HasControls ()) {
655                                 int len = Controls.Count;
656                                 for (int i = 0; i < len; i++) {
657                                         Control c = Controls [i];
658                                         c.RenderControl (writer);
659                                 }
660                         }
661                 }
662
663                 protected virtual object SaveViewState ()
664                 {
665                         if ((stateMask & VISIBLE_CHANGED) != 0) {
666                                 ViewState ["Visible"] = (stateMask & VISIBLE) != 0;
667                         } else if (_viewState == null) {
668                                 return null;
669                         }
670
671                         return _viewState.SaveViewState ();
672                 }
673
674                 protected virtual void TrackViewState()\r
675                 {\r
676                         if (_viewState != null)\r
677                                 _viewState.TrackViewState ();\r
678
679                         stateMask |= TRACK_VIEWSTATE;
680                 }\r
681                 \r
682                 public virtual void Dispose()\r
683                 {\r
684                         if (_events != null)\r
685                         {\r
686                                 EventHandler eh = (EventHandler) _events [DisposedEvent];\r
687                                 if (eh != null)\r
688                                         eh(this, EventArgs.Empty);\r
689                         }\r
690                 }\r
691
692                 [WebCategory ("FIXME")]
693                 [WebSysDescription ("Raised when the contols databound properties are evaluated.")]\r
694                 public event EventHandler DataBinding //DIT\r
695                 {\r
696                         add\r
697                         {\r
698                                 Events.AddHandler(DataBindingEvent, value);\r
699                         }\r
700                         remove\r
701                         {\r
702                                 Events.RemoveHandler(DataBindingEvent, value);\r
703                         }\r
704                 }
705
706                 [WebSysDescription ("Raised when the contol is disposed.")]\r
707                 public event EventHandler Disposed //DIT\r
708                 {\r
709                         add\r
710                         {\r
711                                 Events.AddHandler(DisposedEvent, value);\r
712                         }\r
713                         remove\r
714                         {\r
715                                 Events.RemoveHandler(DisposedEvent, value);\r
716                         }\r
717                 }
718
719                 [WebSysDescription ("Raised when the page containing the control is initialized.")]\r
720                 public event EventHandler Init //DIT\r
721                 {\r
722                         add\r
723                         {\r
724                                 Events.AddHandler(InitEvent, value);\r
725                         }\r
726                         remove\r
727                         {\r
728                                 Events.RemoveHandler(InitEvent, value);\r
729                         }\r
730                 }
731
732                 [WebSysDescription ("Raised after the page containing the control has been loaded.")]\r
733                 public event EventHandler Load //DIT\r
734                 {\r
735                         add\r
736                         {\r
737                                 Events.AddHandler(LoadEvent, value);\r
738                         }\r
739                         remove\r
740                         {\r
741                                 Events.RemoveHandler(LoadEvent, value);\r
742                         }\r
743                 }
744
745                 [WebSysDescription ("Raised before the page containing the control is rendered.")]\r
746                 public event EventHandler PreRender //DIT\r
747                 {\r
748                         add\r
749                         {\r
750                                 Events.AddHandler(PreRenderEvent, value);\r
751                         }\r
752                         remove\r
753                         {\r
754                                 Events.RemoveHandler(PreRenderEvent, value);\r
755                         }\r
756                 }
757
758                 [WebSysDescription ("Raised when the page containing the control is unloaded.")]\r
759                 public event EventHandler Unload //DIT\r
760                 {\r
761                         add\r
762                         {\r
763                                 Events.AddHandler(UnloadEvent, value);\r
764                         }\r
765                         remove\r
766                         {\r
767                                 Events.RemoveHandler(UnloadEvent, value);\r
768                         }\r
769                 }\r
770 \r
771                 public virtual void DataBind() //DIT\r
772                 {
773                         #if NET_2_0
774                         bool foundDataItem = false;
775                         
776                         if ((stateMask & IS_NAMING_CONTAINER) != 0 && Page != null) {
777                                 object o = DataBinder.GetDataItem (this, out foundDataItem);
778                                 if (foundDataItem)
779                                         Page.PushDataItemContext (o);
780                         }
781                         
782                         try {
783                         #endif
784                                 
785                                 OnDataBinding (EventArgs.Empty);
786                                 DataBindChildren();
787                         
788                         #if NET_2_0
789                         } finally {
790                                 if (foundDataItem)
791                                         Page.PopDataItemContext ();
792                         }
793                         #endif
794                 }
795                 
796                 #if NET_2_0
797                 protected virtual
798                 #endif
799                 
800                 void DataBindChildren ()
801                 {
802                         if (!HasControls ())
803                                 return;
804                         
805                         int len = Controls.Count;
806                         for (int i = 0; i < len; i++) {
807                                 Control c = Controls [i];
808                                 c.DataBind ();
809                         }
810                 }
811
812
813                 public virtual bool HasControls ()
814                 {
815                         return (_controls != null && _controls.Count > 0);
816                 }
817
818                 public void RenderControl(HtmlTextWriter writer)
819                 {
820                         if ((stateMask & VISIBLE) != 0)
821                                 Render(writer);
822                 }
823
824                 public string ResolveUrl(string relativeUrl)
825                 {
826                         if (relativeUrl == null)
827                                 throw new ArgumentNullException ("relativeUrl");
828
829                         if (relativeUrl == "")
830                                 return "";
831
832                         if (relativeUrl [0] == '#')
833                                 return relativeUrl;
834                         
835                         string ts = TemplateSourceDirectory;
836                         if (ts == "" || !UrlUtils.IsRelativeUrl (relativeUrl))
837                                 return relativeUrl;
838
839                         HttpResponse resp = Context.Response;
840                         return resp.ApplyAppPathModifier (UrlUtils.Combine (ts, relativeUrl));
841                 }
842                 
843                 internal bool HasRenderMethodDelegate () {
844                         return _renderMethodDelegate != null;
845                 }
846
847                 [EditorBrowsable (EditorBrowsableState.Advanced)]\r
848                 public void SetRenderMethodDelegate(RenderMethod renderMethod) //DIT\r
849                 {\r
850                         _renderMethodDelegate = renderMethod;\r
851                 }\r
852 \r
853                 internal void LoadRecursive()\r
854                 {\r
855                         OnLoad (EventArgs.Empty);\r
856                         if (HasControls ()) {\r
857                                 int len = Controls.Count;
858                                 for (int i=0;i<len;i++)
859                                 {\r
860                                         Control c = Controls[i];\r
861                                         c.LoadRecursive ();\r
862                                 }\r
863                         }\r
864                         stateMask |= LOADED;
865                 }\r
866 \r
867                 internal void UnloadRecursive(Boolean dispose)\r
868                 {\r
869                         if (HasControls ()) {\r
870                                 int len = Controls.Count;
871                                 for (int i=0;i<len;i++)
872                                 {\r
873                                         Control c = Controls[i];                                        \r
874                                         c.UnloadRecursive (dispose);\r
875                                 }
876                         }\r
877 \r
878                         OnUnload (EventArgs.Empty);\r
879                         if (dispose)\r
880                                 Dispose();\r
881                 }\r
882
883                 internal void PreRenderRecursiveInternal()
884                 {
885                         if ((stateMask & VISIBLE) != 0) {
886                                 EnsureChildControls ();
887                                 OnPreRender (EventArgs.Empty);
888                                 if (!HasControls ())
889                                         return;
890                                 
891                                 int len = Controls.Count;
892                                 for (int i=0;i<len;i++)
893                                 {\r
894                                         Control c = Controls[i];
895                                         c.PreRenderRecursiveInternal ();
896                                 }
897                         }
898                         stateMask |= PRERENDERED;
899                 }
900
901                 internal void InitRecursive(Control namingContainer)\r
902                 {\r
903                         if (HasControls ()) {\r
904                                 if ((stateMask & IS_NAMING_CONTAINER) != 0)
905                                         namingContainer = this;\r
906 \r
907                                 if (namingContainer != null && \r
908                                     namingContainer._userId == null &&\r
909                                     namingContainer.AutoID)\r
910                                         namingContainer._userId = namingContainer.GetDefaultName () + "b";\r
911 \r
912                                 int len = Controls.Count;
913                                 for (int i=0;i<len;i++)
914                                 {\r
915                                         Control c = Controls[i];\r
916                                         c._page = Page;\r
917                                         c._namingContainer = namingContainer;\r
918                                         if (namingContainer != null && c._userId == null && c.AutoID)\r
919                                                 c._userId = namingContainer.GetDefaultName () + "c";\r
920                                         c.InitRecursive (namingContainer);      \r
921                                 }
922                         }\r
923 \r
924                         stateMask |= INITING;
925                         OnInit (EventArgs.Empty);\r
926                         TrackViewState ();\r
927                         stateMask |= INITED;
928                         stateMask &= ~INITING;
929                 }\r
930
931                 internal object SaveViewStateRecursive ()
932                 {
933                         if (!EnableViewState)
934                                 return null;
935
936                         ArrayList controlList = null;
937                         ArrayList controlStates = null;
938
939                         int idx = -1;
940                         if (HasControls ())
941                         {
942                                 int len = Controls.Count;
943                                 for (int i=0;i<len;i++)
944                                 {
945                                         Control ctrl = Controls[i];
946                                         object ctrlState = ctrl.SaveViewStateRecursive ();
947                                         idx++;
948                                         if (ctrlState == null)
949                                                 continue;
950
951                                         if (controlList == null) \r
952                                         {
953                                                 controlList = new ArrayList ();
954                                                 controlStates = new ArrayList ();
955                                         }
956
957                                         controlList.Add (idx);
958                                         controlStates.Add (ctrlState);
959                                 }
960                         }
961
962                         object thisState = SaveViewState ();
963                         if (thisState == null && controlList == null && controlStates == null)
964                                 return null;
965
966                         return new Triplet (thisState, controlList, controlStates);
967                 }
968                 
969                 internal void LoadViewStateRecursive (object savedState)
970                 {
971                         if (!EnableViewState || savedState == null)
972                                 return;
973
974                         Triplet savedInfo = (Triplet) savedState;
975                         LoadViewState (savedInfo.First);
976
977                         ArrayList controlList = savedInfo.Second as ArrayList;
978                         if (controlList == null)
979                                 return;
980                         ArrayList controlStates = savedInfo.Third as ArrayList;
981                         int nControls = controlList.Count;
982                         for (int i = 0; i < nControls; i++) {
983                                 int k = (int) controlList [i];
984                                 if (k < Controls.Count && controlStates != null) {
985                                         Control c = Controls [k];
986                                         c.LoadViewStateRecursive (controlStates [i]);
987                                 } else {
988                                         if (pendingVS == null)
989                                                 pendingVS = new Hashtable ();
990
991                                         pendingVS [k] = controlStates [i];
992                                 }
993                         }
994
995                         stateMask |= VIEWSTATE_LOADED;
996                 }
997                 
998                 void IParserAccessor.AddParsedSubObject(object obj)\r
999                 {\r
1000                         AddParsedSubObject(obj);\r
1001                 }\r
1002                 \r
1003                 DataBindingCollection IDataBindingsAccessor.DataBindings\r
1004                 {\r
1005                         get\r
1006                         {\r
1007                                 if(dataBindings == null)\r
1008                                         dataBindings = new DataBindingCollection();\r
1009                                 return dataBindings;\r
1010                         }\r
1011                 }\r
1012                 \r
1013                 bool IDataBindingsAccessor.HasDataBindings\r
1014                 {\r
1015                         get\r
1016                         {\r
1017                                 return (dataBindings!=null && dataBindings.Count>0);\r
1018                         }\r
1019                 }\r
1020  
1021                 internal bool AutoID
1022                 {
1023                         get { return (stateMask & AUTOID) != 0; }
1024                         set {
1025                                 if (value == false && (stateMask & IS_NAMING_CONTAINER) != 0)
1026                                         return;
1027
1028                                 SetMask (AUTOID, value);
1029                         }
1030                 }
1031
1032                 internal void PreventAutoID()\r
1033                 {\r
1034                         AutoID = false;\r
1035                 }\r
1036                 \r
1037                 protected internal virtual void RemovedControl (Control control)\r
1038                 {\r
1039                         control.UnloadRecursive (false);\r
1040                         control._parent = null;\r
1041                         control._page = null;\r
1042                         control._namingContainer = null;\r
1043                 }\r
1044 \r
1045 #if NET_2_0
1046                 protected string GetWebResourceUrl (string resourceName)
1047                 {
1048                         return Page.ClientScript.GetWebResourceUrl (GetType(), resourceName); 
1049                 } 
1050
1051                 string IUrlResolutionService.ResolveClientUrl (string url)
1052                 {
1053                         throw new NotImplementedException ();               
1054                 }
1055
1056                 ControlBuilder IControlBuilderAccessor.ControlBuilder { 
1057                         get {throw new NotImplementedException (); }
1058                 }
1059
1060                 IDictionary IControlDesignerAccessor.GetDesignModeState ()
1061                 {
1062                         throw new NotImplementedException ();               
1063                 }
1064         
1065                 void IControlDesignerAccessor.SetDesignModeState (IDictionary designData)
1066                 {
1067                         throw new NotImplementedException ();               
1068                 }
1069
1070                 void IControlDesignerAccessor.SetOwnerControl (Control control)
1071                 {
1072                         throw new NotImplementedException ();               
1073                 }
1074                 
1075                 IDictionary IControlDesignerAccessor.UserData { 
1076                         get { throw new NotImplementedException (); }
1077                 }
1078        
1079                 ExpressionBindingCollection expressionBindings;
1080
1081                 ExpressionBindingCollection IExpressionsAccessor.Expressions { 
1082                         get { 
1083                                 if (expressionBindings == null)
1084                                         expressionBindings = new ExpressionBindingCollection ();\r
1085                                 return expressionBindings;\r
1086                         } 
1087                 }
1088                 
1089                 bool IExpressionsAccessor.HasExpressions { 
1090                         get {\r
1091                                 return (expressionBindings != null && expressionBindings.Count > 0);\r
1092                         }\r
1093                 }
1094
1095                 [MonoTODO]
1096                 public virtual void Focus()\r
1097                 {\r
1098                         throw new NotImplementedException();\r
1099                 }
1100                 
1101                 protected internal virtual void LoadControlState (object state)
1102                 {
1103                 }
1104                 
1105                 protected internal virtual object SaveControlState ()
1106                 {
1107                         return null;
1108                 }
1109                 
1110 #endif\r
1111         }\r
1112 }\r