2 // System.Web.UI.Control.cs
\r
5 // Bob Smith <bob@thestuff.net>
\r
11 * Maintainer: bob@thestuff.net, gvaish@iitk.ac.in
\r
12 * (C) Bob Smith, Gaurav Vaish
\r
15 //notes: view state only tracks changes after OnInit method is executed for the page request. You can read from it at any time, but cant write to it during rendering.
\r
16 //even more notes: view state info in trackviewstate method description. read later.
\r
17 //Ok, enough notes: what the heck is different between enable view state, and track view state.
\r
18 //Well, maybe not. How does the ViewState know when to track changes? Does it look at the property
\r
19 //on the owning control, or does it have a method/property of its own that gets called?
\r
20 // I think this last question is solved in the Interface for it. Look into this.
\r
23 //init is called when control is first created.
\r
24 //load view state ic called right after init to populate the view state.
\r
25 //loadpostdata is called if ipostbackdatahandler is implemented.
\r
26 //load is called when control is loaded into a page
\r
27 //raisepostdatachangedevent if ipostbackdatahandler is implemented.
\r
28 //raisepostbackevent if ipostbackeventhandler is implemented.
\r
29 //prerender is called when the server is about to render its page object
\r
30 //SaveViewState is called.
\r
31 //Unload then dispose it apears. :)
\r
33 //Naming Container MUST have some methods. What are they? No clue. Help?
\r
35 //read this later. http://gotdotnet.com/quickstart/aspplus/
\r
36 //This to: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconattributesdesign-timesupport.asp
\r
37 //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpcontracefunctionality.asp
\r
39 // Isnt life grand? :)
\r
40 // See the undocumented methods? Gota love um. ;)
\r
41 // ASP.test4_aspx.Page_Load(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6
\r
42 // System.Web.UI.Control.OnLoad(EventArgs e) +67
\r
43 // System.Web.UI.Control.LoadRecursive() +73
\r
44 // System.Web.UI.Page.ProcessRequestMain() +394
\r
46 // ASP.test4_aspx.Page_Unload(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6
\r
47 // System.EventHandler.Invoke(Object sender, EventArgs e) +0
\r
48 // System.Web.UI.Control.OnUnload(EventArgs e) +67
\r
49 // System.Web.UI.Control.UnloadRecursive(Boolean dispose) +78
\r
50 // System.Web.UI.Page.ProcessRequest() +194
\r
51 // System.Web.UI.Page.ProcessRequest(HttpContext context) +18
\r
52 // System.Web.CallHandlerExecutionStep.Execute() +179
\r
53 // System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +87
\r
56 // ASP.test4_aspx.Page_Unload(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6
\r
57 // System.Web.UI.Control.OnUnload(EventArgs e) +67
\r
58 // System.Web.UI.Control.UnloadRecursive(Boolean dispose) +78
\r
59 // System.Web.UI.Page.ProcessRequest()
\r
61 // ASP.test4_aspx.Page_Kill(Object Sender, EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6
\r
62 // System.Web.UI.Control.OnPreRender(EventArgs e) +67
\r
63 // System.Web.UI.Control.PreRenderRecursiveInternal() +61
\r
64 // System.Web.UI.Page.ProcessRequestMain() +753
\r
66 // ASP.test4_aspx.OnInit(EventArgs e) in \\genfs2\www24\bobsmith11\test4.aspx:6
\r
67 // System.Web.UI.Control.InitRecursive(Control namingContainer) +202
\r
68 // System.Web.UI.Page.ProcessRequestMain() +120
\r
70 // ASP.test4_aspx.SaveViewState() in \\genfs2\www24\bobsmith11\test4.aspx:12
\r
71 // System.Web.UI.Control.SaveViewStateRecursive() +51
\r
72 // System.Web.UI.Page.SavePageViewState() +174
\r
73 // System.Web.UI.Page.ProcessRequestMain() +861
\r
75 // ASP.test_aspx.LoadViewState(Object t) +28
\r
76 // System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +125
\r
77 // System.Web.UI.Page.LoadPageViewState() +182
\r
78 // System.Web.UI.Page.ProcessRequestMain() +256
\r
81 using System.Collections;
\r
83 using System.ComponentModel;
\r
85 namespace System.Web.UI
\r
87 public class Control : IComponent, IDisposable, IParserAccessor, IDataBindingsAccessor
\r
89 private static readonly object DataBindingEvent = new object();
\r
90 private static readonly object DisposedEvent = new object();
\r
91 private static readonly object InitEvent = new object();
\r
92 private static readonly object LoadEvent = new object();
\r
93 private static readonly object PreRenderEvent = new object();
\r
94 private static readonly object UnloadEvent = new object();
\r
95 private string _userId = null;
\r
96 private string _cachedUserId = null;
\r
97 private string _cachedClientId = null;
\r
98 private ControlCollection _controls = null;
\r
99 private bool _enableViewState = true;
\r
100 private IDictionary _childViewStates = null; //TODO: Not sure datatype. Placeholder guess.
\r
101 private bool _isNamingContainer = false;
\r
102 private Control _namingContainer = null;
\r
103 private Page _page = null;
\r
104 private Control _parent = null;
\r
105 private ISite _site = null;
\r
106 private bool _visible = true;
\r
107 private HttpContext _context = null;
\r
108 private bool _childControlsCreated = false;
\r
109 private StateBag _viewState = null;
\r
110 private bool _trackViewState = false;
\r
111 private EventHandlerList _events = new EventHandlerList();
\r
112 private RenderMethod _renderMethodDelegate = null;
\r
113 private bool autoID = true;
\r
114 private bool creatingControls = false;
\r
116 private DataBindingCollection dataBindings = null;
\r
120 if (this is INamingContainer) _isNamingContainer = true;
\r
123 public Control BindingContainer
\r
126 Control container = NamingContainer;
\r
127 if (_isNamingContainer)
\r
128 container = container.BindingContainer;
\r
133 public virtual string ClientID //DIT
\r
137 if (_cachedUserId != null && _cachedClientId != null)
\r
138 return _cachedClientId;
\r
139 _cachedUserId = UniqueID.Replace(':', '_');
\r
140 return _cachedUserId;
\r
143 public virtual ControlCollection Controls //DIT
\r
147 if (_controls == null) _controls = CreateControlCollection();
\r
151 public virtual bool EnableViewState //DIT
\r
155 return _enableViewState;
\r
159 _enableViewState = value;
\r
162 public virtual string ID
\r
170 if (value == null || value == "") return;
\r
172 _cachedUserId = null;
\r
173 //TODO: Some Naming Container stuff here I think.
\r
176 public virtual Control NamingContainer //DIT
\r
180 if (_namingContainer == null && _parent != null)
\r
182 if (_parent._isNamingContainer == false)
\r
183 _namingContainer = _parent.NamingContainer;
\r
185 _namingContainer = _parent;
\r
187 return _namingContainer;
\r
190 public virtual Page Page //DIT
\r
194 if (_page == null && _parent != null) _page = _parent.Page;
\r
202 public virtual Control Parent //DIT
\r
209 public ISite Site //DIT
\r
220 public virtual string TemplateSourceDirectory
\r
224 return Context.Request.ApplicationPath; //TODO: Dont think this is right.
\r
229 public virtual string UniqueID
\r
233 //TODO: Some Naming container methods here. What are they? Why arnt they declared?
\r
234 //Note: Nuked the old stuff here. Was total crap. :)
\r
238 public virtual bool Visible
\r
242 if (_visible == false)
\r
245 if (_parent != null)
\r
246 return _parent.Visible;
\r
255 protected bool ChildControlsCreated //DIT
\r
259 return _childControlsCreated;
\r
263 if (value == false && _childControlsCreated == true)
\r
265 _childControlsCreated = value;
\r
268 protected virtual HttpContext Context //DIT
\r
272 HttpContext context;
\r
273 if (_context != null)
\r
275 if (_parent == null)
\r
276 return HttpContext.Current;
\r
277 context = _parent.Context;
\r
278 if (context != null)
\r
280 return HttpContext.Current;
\r
283 protected EventHandlerList Events //DIT
\r
287 if (_events == null)
\r
289 _events = new EventHandlerList();
\r
294 protected bool HasChildViewState //DIT
\r
298 if (_childViewStates == null) return false;
\r
302 protected bool IsTrackingViewState //DIT
\r
306 return _trackViewState;
\r
309 protected virtual StateBag ViewState
\r
313 if(_viewState == null)
\r
315 _viewState = new StateBag(ViewStateIgnoresCase);
\r
316 if(IsTrackingViewState)
\r
317 _viewState.TrackViewState();
\r
322 protected virtual bool ViewStateIgnoresCase //DIT
\r
330 private int defaultNumberID;
\r
331 protected internal virtual void AddedControl (Control control, int index)
\r
333 /* Ensure the control don't have more than 1 parent */
\r
334 if (control._parent != null)
\r
335 control._parent.Controls.Remove (control);
\r
337 control._parent = this;
\r
338 control._page = Page;
\r
340 // Without this, DataBoundLiteralControl crashes in OnDataBound event.
\r
341 Control namingContainer = NamingContainer;
\r
342 if (namingContainer != null)
\r
343 control._namingContainer = namingContainer;
\r
345 if (control.AutoID == true && control.ID == null)
\r
346 control.ID = "_ctrl_" + defaultNumberID++;
\r
349 protected virtual void AddParsedSubObject(object obj) //DIT
\r
351 Control c = (Control)obj;
\r
352 if (c != null) Controls.Add(c);
\r
354 protected void BuildProfileTree(string parentId, bool calcViewState)
\r
358 protected void ClearChildViewState()
\r
361 //Not quite sure about this. an example clears children then calls this, so I think
\r
362 //view state is local to the current object, not children.
\r
364 protected virtual void CreateChildControls() {} //DIT
\r
365 protected virtual ControlCollection CreateControlCollection() //DIT
\r
367 return new ControlCollection(this);
\r
370 protected virtual void EnsureChildControls () //DIT
\r
372 if (ChildControlsCreated == false && !creatingControls) {
\r
373 creatingControls = true;
\r
374 CreateChildControls();
\r
375 ChildControlsCreated = true;
\r
376 creatingControls = false;
\r
380 protected virtual Control FindControl(string id, int pathOffset)
\r
382 //TODO: I think there is Naming Container stuff here. Redo.
\r
385 for (i = pathOffset; i < _controls.Count; i++){
\r
386 ctrl = _controls [i];
\r
391 if (ctrl.Controls.Count > 0){
\r
392 Control other = ctrl.FindControl (id);
\r
401 protected virtual void LoadViewState(object savedState)
\r
403 ViewState.LoadViewState (savedState);
\r
407 protected string MapPathSecure(string virtualPath)
\r
409 //TODO: Need to read up on security+web.
\r
410 //Return the same path. So AdRotator can read its config file.
\r
411 return virtualPath;
\r
413 protected virtual bool OnBubbleEvent(object source, EventArgs args) //DIT
\r
417 protected virtual void OnDataBinding(EventArgs e) //DIT
\r
419 if (_events != null)
\r
421 EventHandler eh = (EventHandler)(_events[DataBindingEvent]);
\r
422 if (eh != null) eh(this, e);
\r
425 protected virtual void OnInit(EventArgs e) //DIT
\r
427 if (_events != null)
\r
429 EventHandler eh = (EventHandler)(_events[InitEvent]);
\r
430 if (eh != null) eh(this, e);
\r
433 protected virtual void OnLoad(EventArgs e) //DIT
\r
435 if (_events != null)
\r
437 EventHandler eh = (EventHandler)(_events[LoadEvent]);
\r
438 if (eh != null) eh(this, e);
\r
441 protected virtual void OnPreRender(EventArgs e) //DIT
\r
443 if (_events != null)
\r
445 EventHandler eh = (EventHandler)(_events[PreRenderEvent]);
\r
446 if (eh != null) eh(this, e);
\r
449 protected virtual void OnUnload(EventArgs e) //DIT
\r
451 if (_events != null)
\r
453 EventHandler eh = (EventHandler)(_events[UnloadEvent]);
\r
454 if (eh != null) eh(this, e);
\r
459 protected void RaiseBubbleEvent(object source, EventArgs args)
\r
461 throw new NotImplementedException();
\r
464 protected virtual void Render(HtmlTextWriter writer) //DIT
\r
466 RenderChildren(writer);
\r
468 protected virtual void RenderChildren(HtmlTextWriter writer) //DIT
\r
470 if (_renderMethodDelegate != null)
\r
471 _renderMethodDelegate(writer, this);
\r
472 else if (_controls != null)
\r
473 foreach (Control c in _controls)
\r
474 c.RenderControl(writer);
\r
477 protected virtual object SaveViewState ()
\r
479 return ViewState.SaveViewState ();
\r
482 protected virtual void TrackViewState()
\r
484 _trackViewState = true;
\r
488 public virtual void Dispose()
\r
490 //TODO: nuke stuff.
\r
491 throw new NotImplementedException();
\r
493 if (_events != null)
\r
495 EventHandler eh = (EventHandler)(_events[DisposedEvent]);
\r
496 if (eh != null) eh(this, e);
\r
501 public bool HasChildren
\r
503 get { return (_controls != null && _controls.Count > 0); }
\r
506 public event EventHandler DataBinding //DIT
\r
510 Events.AddHandler(DataBindingEvent, value);
\r
514 Events.RemoveHandler(DataBindingEvent, value);
\r
517 public event EventHandler Disposed //DIT
\r
521 Events.AddHandler(DisposedEvent, value);
\r
525 Events.RemoveHandler(DisposedEvent, value);
\r
528 public event EventHandler Init //DIT
\r
532 Events.AddHandler(InitEvent, value);
\r
536 Events.RemoveHandler(InitEvent, value);
\r
539 public event EventHandler Load //DIT
\r
543 Events.AddHandler(LoadEvent, value);
\r
547 Events.RemoveHandler(LoadEvent, value);
\r
550 public event EventHandler PreRender //DIT
\r
554 Events.AddHandler(PreRenderEvent, value);
\r
558 Events.RemoveHandler(PreRenderEvent, value);
\r
561 public event EventHandler Unload //DIT
\r
565 Events.AddHandler(UnloadEvent, value);
\r
569 Events.RemoveHandler(UnloadEvent, value);
\r
572 public virtual void DataBind() //DIT
\r
574 OnDataBinding(EventArgs.Empty);
\r
575 if (_controls != null)
\r
576 foreach (Control c in _controls)
\r
579 public virtual Control FindControl(string id) //DIT
\r
581 return FindControl(id, 0);
\r
583 public virtual bool HasControls() //DIT
\r
585 if (_controls != null && _controls.Count >0) return true;
\r
588 public void RenderControl(HtmlTextWriter writer)
\r
592 // By now, PreRender is fired here.
\r
593 OnPreRender (EventArgs.Empty); //FIXME
\r
594 //TODO: Something about tracing here.
\r
600 public string ResolveUrl(string relativeUrl)
\r
602 return relativeUrl;
\r
604 public void SetRenderMethodDelegate(RenderMethod renderMethod) //DIT
\r
606 _renderMethodDelegate = renderMethod;
\r
608 protected void LoadRecursive()
\r
610 OnLoad(EventArgs.Empty);
\r
611 if (_controls != null) foreach (Control c in _controls) c.LoadRecursive();
\r
613 protected void UnloadRecursive(Boolean dispose)
\r
615 OnUnload(EventArgs.Empty);
\r
616 if (_controls != null) foreach (Control c in _controls) c.UnloadRecursive(dispose);
\r
617 if (dispose) Dispose();
\r
619 protected void PreRenderRecursiveInternal()
\r
621 OnPreRender(EventArgs.Empty);
\r
622 if (_controls != null) foreach (Control c in _controls) c.PreRenderRecursiveInternal();
\r
624 protected void InitRecursive(Control namingContainer)
\r
626 if (_controls != null) foreach (Control c in _controls) c.InitRecursive(namingContainer);
\r
627 OnInit(EventArgs.Empty);
\r
630 protected object SaveViewStateRecursive()
\r
632 ArrayList controlList = new ArrayList ();
\r
633 ArrayList controlStates = new ArrayList ();
\r
635 foreach (Control ctrl in Controls){
\r
636 controlList.Add (ctrl);
\r
637 controlStates.Add (ctrl.SaveViewStateRecursive ());
\r
640 return new Triplet (SaveViewState (), controlList, controlStates);
\r
644 protected void LoadViewStateRecursive(Object savedState)
\r
646 throw new NotImplementedException ();
\r
649 void IParserAccessor.AddParsedSubObject(object obj)
\r
651 AddParsedSubObject(obj);
\r
654 DataBindingCollection IDataBindingsAccessor.DataBindings
\r
658 if(dataBindings == null)
\r
659 dataBindings = new DataBindingCollection();
\r
660 return dataBindings;
\r
664 bool IDataBindingsAccessor.HasDataBindings
\r
668 return (dataBindings!=null && dataBindings.Count>0);
\r
672 internal bool AutoID
\r
674 get { return autoID; }
\r
675 set { autoID = value; }
\r
678 internal void PreventAutoID()
\r
683 //TODO: I think there are some needed Interface implementations to do here.
\r
684 //TODO: Find api for INamingContainer.
\r