2 // System.Web.UI.Control.cs
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 // Marek Habersack <mhabersack@novell.com>
12 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
13 // (C) 2004-2010 Novell, Inc. (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.ComponentModel;
40 using System.ComponentModel.Design;
41 using System.ComponentModel.Design.Serialization;
42 using System.Globalization;
44 using System.Security.Permissions;
46 using System.Web.Util;
47 using System.Web.UI.Adapters;
49 namespace System.Web.UI
52 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
53 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
55 [DefaultProperty ("ID"), DesignerCategory ("Code"), ToolboxItemFilter ("System.Web.UI", ToolboxItemFilterType.Require)]
56 [ToolboxItem ("System.Web.UI.Design.WebControlToolboxItem, " + Consts.AssemblySystem_Design)]
57 [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
58 [DesignerSerializer ("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, " + Consts.AssemblyMicrosoft_VisualStudio_Web,
59 "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
62 public partial class Control : IComponent, IDisposable, IParserAccessor, IDataBindingsAccessor, IUrlResolutionService, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
64 internal static readonly object DataBindingEvent = new object ();
65 internal static readonly object DisposedEvent = new object ();
66 internal static readonly object InitEvent = new object ();
67 internal static readonly object LoadEvent = new object ();
68 internal static readonly object PreRenderEvent = new object ();
69 internal static readonly object UnloadEvent = new object ();
70 internal static string [] defaultNameArray;
73 const int databinding_mask = 1;
74 const int disposed_mask = 1 << 1;
75 const int init_mask = 1 << 2;
76 const int load_mask = 1 << 3;
77 const int prerender_mask = 1 << 4;
78 const int unload_mask = 1 << 5;
82 static Dictionary <Type, bool> loadViewStateByIDCache;
83 bool? loadViewStateByID;
86 ControlCollection _controls;
87 Control _namingContainer;
92 EventHandlerList _events;
93 RenderMethod _renderMethodDelegate;
94 Hashtable _controlsCache;
97 DataBindingCollection dataBindings;
98 Hashtable pendingVS; // may hold unused viewstate data from child controls
99 TemplateControl _templateControl;
100 bool _isChildControlStateCleared;
101 string _templateSourceDirectory;
105 const int ENABLE_VIEWSTATE = 1;
106 const int VISIBLE = 1 << 1;
107 const int AUTOID = 1 << 2;
108 const int CREATING_CONTROLS = 1 << 3;
109 const int BINDING_CONTAINER = 1 << 4;
110 const int AUTO_EVENT_WIREUP = 1 << 5;
111 const int IS_NAMING_CONTAINER = 1 << 6;
112 const int VISIBLE_CHANGED = 1 << 7;
113 const int TRACK_VIEWSTATE = 1 << 8;
114 const int CHILD_CONTROLS_CREATED = 1 << 9;
115 const int ID_SET = 1 << 10;
116 const int INITED = 1 << 11;
117 const int INITING = 1 << 12;
118 const int VIEWSTATE_LOADED = 1 << 13;
119 const int LOADED = 1 << 14;
120 const int PRERENDERED = 1 << 15;
121 const int ENABLE_THEMING = 1 << 16;
122 const int AUTOID_SET = 1 << 17;
123 const int REMOVED = 1 << 18;
128 defaultNameArray = new string [100];
129 for (int i = 0; i < 100; i++)
130 defaultNameArray [i] = String.Concat ("ctl", i.ToString ("D2"));
135 stateMask = ENABLE_VIEWSTATE | VISIBLE | AUTOID | BINDING_CONTAINER | AUTO_EVENT_WIREUP;
136 if (this is INamingContainer)
137 stateMask |= IS_NAMING_CONTAINER;
140 ControlAdapter adapter;
141 bool did_adapter_lookup;
142 protected internal ControlAdapter Adapter {
144 if (!did_adapter_lookup) {
145 adapter = ResolveAdapter ();
147 adapter.control = this;
148 did_adapter_lookup = true;
154 string _appRelativeTemplateSourceDirectory = null;
156 [EditorBrowsable (EditorBrowsableState.Advanced)]
158 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
159 public string AppRelativeTemplateSourceDirectory {
161 if (_appRelativeTemplateSourceDirectory != null)
162 return _appRelativeTemplateSourceDirectory;
164 string tempSrcDir = null;
165 TemplateControl templateControl = TemplateControl;
166 if (templateControl != null) {
167 string templateVirtualPath = templateControl.AppRelativeVirtualPath;
168 if (!String.IsNullOrEmpty (templateVirtualPath))
169 tempSrcDir = VirtualPathUtility.GetDirectory (templateVirtualPath, false);
172 _appRelativeTemplateSourceDirectory = (tempSrcDir != null) ? tempSrcDir : VirtualPathUtility.ToAppRelative (TemplateSourceDirectory);
173 return _appRelativeTemplateSourceDirectory;
175 [EditorBrowsable (EditorBrowsableState.Never)]
177 _appRelativeTemplateSourceDirectory = value;
178 _templateSourceDirectory = null;
182 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
183 [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)]
184 public Control BindingContainer {
186 Control container = NamingContainer;
187 if (container != null && container is INonBindingContainer || (stateMask & BINDING_CONTAINER) == 0)
188 container = container.BindingContainer;
194 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
196 [WebSysDescription ("An Identification of the control that is rendered.")]
197 public virtual string ClientID {
199 string client = UniqueID;
202 client = UniqueID2ClientID (client);
209 internal string UniqueID2ClientID (string uniqueId)
211 return uniqueId.Replace (IdSeparator, ClientIDSeparator);
214 protected char ClientIDSeparator {
219 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
221 [WebSysDescription ("The child controls of this control.")]
222 public virtual ControlCollection Controls { //DIT
224 if (_controls == null)
225 _controls = CreateControlCollection ();
230 [MonoTODO ("revisit once we have a real design strategy")]
231 protected internal bool DesignMode {
232 get { return false; }
235 [DefaultValue (true), WebCategory ("Behavior")]
236 [WebSysDescription ("An Identification of the control that is rendered.")]
238 public virtual bool EnableViewState {
239 get { return ((stateMask & ENABLE_VIEWSTATE) != 0); }
240 set { SetMask (ENABLE_VIEWSTATE, value); }
243 [MergableProperty (false), ParenthesizePropertyName (true)]
244 [WebSysDescription ("The name of the control that is rendered.")]
245 [Filterable (false), Themeable (false)]
246 public virtual string ID {
247 get { return (((stateMask & ID_SET) != 0) ? _userId : null); }
250 if (value != null && value.Length == 0)
259 protected internal bool IsChildControlStateCleared {
260 get { return _isChildControlStateCleared; }
263 protected bool LoadViewStateByID {
265 if (loadViewStateByID == null)
266 loadViewStateByID = IsLoadViewStateByID ();
268 return (bool)loadViewStateByID;
272 protected internal bool IsViewStateEnabled {
274 for (Control control = this; control != null; control = control.Parent)
275 if (!control.EnableViewState)
282 protected char IdSeparator {
286 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
288 [WebSysDescription ("The container that this control is part of. The control's name has to be unique within the container.")]
289 public virtual Control NamingContainer {
291 if (_namingContainer == null && _parent != null) {
292 if ((_parent.stateMask & IS_NAMING_CONTAINER) == 0)
293 _namingContainer = _parent.NamingContainer;
295 _namingContainer = _parent;
298 return _namingContainer;
302 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
304 [WebSysDescription ("The webpage that this control resides on.")]
306 public virtual Page Page { //DIT
309 if (NamingContainer != null)
310 _page = NamingContainer.Page;
311 else if (Parent != null)
317 set { _page = value; }
320 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
322 [WebSysDescription ("The parent control of this control.")]
323 public virtual Control Parent { //DIT
324 get { return _parent; }
327 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
328 [EditorBrowsable (EditorBrowsableState.Advanced), Browsable (false)]
329 [WebSysDescription ("The site this control is part of.")]
330 public ISite Site { //DIT
331 get { return _site; }
332 set { _site = value; }
336 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
337 public TemplateControl TemplateControl {
338 get { return TemplateControlInternal; }
340 [EditorBrowsable (EditorBrowsableState.Never)]
341 set { _templateControl = value; }
344 internal virtual TemplateControl TemplateControlInternal {
346 if (_templateControl != null)
347 return _templateControl;
349 return _parent.TemplateControl;
355 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
357 [WebSysDescription ("A virtual directory containing the parent of the control.")]
358 public virtual string TemplateSourceDirectory {
360 if (_templateSourceDirectory == null) {
361 TemplateControl tc = TemplateControl;
364 HttpContext ctx = Context;
366 _templateSourceDirectory = VirtualPathUtility.GetDirectory (ctx.Request.CurrentExecutionFilePath);
367 } else if (tc != this)
368 _templateSourceDirectory = tc.TemplateSourceDirectory;
370 if (_templateSourceDirectory == null && this is TemplateControl) {
371 string path = ((TemplateControl) this).AppRelativeVirtualPath;
374 string ret = VirtualPathUtility.GetDirectory (VirtualPathUtility.ToAbsolute (path));
375 int len = ret.Length;
378 if (ret [--len] == '/')
379 _templateSourceDirectory = ret.Substring (0, len);
381 _templateSourceDirectory = String.Empty;
383 if (_templateSourceDirectory == null)
384 _templateSourceDirectory = String.Empty;
387 return _templateSourceDirectory;
392 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
394 [WebSysDescription ("The unique ID of the control.")]
395 public virtual string UniqueID {
397 if (uniqueID != null)
400 if (NamingContainer == null)
405 string prefix = NamingContainer.UniqueID;
406 if (NamingContainer == Page || prefix == null) {
409 if (getFacesContext () != null)
410 uniqueID = getFacesContext ().getExternalContext ().encodeNamespace (uniqueID);
415 uniqueID = prefix + IdSeparator + _userId;
420 void SetMask (int m, bool val) {
427 [DefaultValue (true), Bindable (true), WebCategory ("Behavior")]
428 [WebSysDescription ("Visiblity state of the control.")]
429 public virtual bool Visible {
431 if ((stateMask & VISIBLE) == 0)
435 return _parent.Visible;
441 if ((value && (stateMask & VISIBLE) == 0) ||
442 (!value && (stateMask & VISIBLE) != 0)) {
443 if (IsTrackingViewState)
444 stateMask |= VISIBLE_CHANGED;
447 SetMask (VISIBLE, value);
451 protected bool ChildControlsCreated {
452 get { return ((stateMask & CHILD_CONTROLS_CREATED) != 0); }
454 if (value == false && (stateMask & CHILD_CONTROLS_CREATED) != 0) {
455 if (_controls != null)
459 SetMask (CHILD_CONTROLS_CREATED, value);
464 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
465 protected internal virtual HttpContext Context { //DIT
471 return HttpContext.Current;
475 protected EventHandlerList Events {
478 _events = new EventHandlerList ();
483 protected bool HasChildViewState {
484 get { return (pendingVS != null && pendingVS.Count > 0); }
487 protected bool IsTrackingViewState {
488 get { return ((stateMask & TRACK_VIEWSTATE) != 0); }
492 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
493 [WebSysDescription ("ViewState")]
494 protected virtual StateBag ViewState {
496 if (_viewState == null)
497 _viewState = new StateBag (ViewStateIgnoresCase);
499 if (IsTrackingViewState)
500 _viewState.TrackViewState ();
507 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
508 protected virtual bool ViewStateIgnoresCase {
509 get { return false; }
512 internal bool AutoEventWireup {
513 get { return (stateMask & AUTO_EVENT_WIREUP) != 0; }
514 set { SetMask (AUTO_EVENT_WIREUP, value); }
517 internal void SetBindingContainer (bool isBC)
519 SetMask (BINDING_CONTAINER, isBC);
522 internal void ResetChildNames ()
524 ResetChildNames (-1);
527 internal void ResetChildNames (int value)
532 defaultNumberID = value;
535 internal int GetDefaultNumberID ()
537 return defaultNumberID;
540 string GetDefaultName ()
543 if (defaultNumberID > 99)
544 defaultName = "ctl" + defaultNumberID++;
546 defaultName = defaultNameArray [defaultNumberID++];
550 void NullifyUniqueID ()
556 for (int i = 0; i < _controls.Count; i++)
557 _controls [i].NullifyUniqueID ();
560 bool IsLoadViewStateByID ()
562 if (loadViewStateByIDCache == null)
563 loadViewStateByIDCache = new Dictionary <Type, bool> ();
566 Type myType = GetType ();
567 if (loadViewStateByIDCache.TryGetValue (myType, out ret))
570 System.ComponentModel.AttributeCollection attrs = TypeDescriptor.GetAttributes (myType);
571 if (attrs != null || attrs.Count > 0) {
573 foreach (Attribute attr in attrs) {
574 if (attr is ViewStateModeByIdAttribute) {
582 loadViewStateByIDCache.Add (myType, ret);
586 protected internal virtual void AddedControl (Control control, int index)
588 ResetControlsCache ();
590 /* Ensure the control don't have more than 1 parent */
591 if (control._parent != null)
592 control._parent.Controls.Remove (control);
594 control._parent = this;
595 Control nc = ((stateMask & IS_NAMING_CONTAINER) != 0) ? this : NamingContainer;
597 if ((stateMask & (INITING | INITED)) != 0) {
598 control.InitRecursive (nc);
599 control.SetMask (REMOVED, false);
601 control.SetNamingContainer (nc);
602 control.SetMask (REMOVED, false);
606 if ((stateMask & (VIEWSTATE_LOADED | LOADED)) != 0) {
607 if (pendingVS != null) {
609 bool byId = LoadViewStateByID;
618 vs = pendingVS [index];
623 pendingVS.Remove (id);
625 pendingVS.Remove (index);
627 if (pendingVS.Count == 0)
630 control.LoadViewStateRecursive (vs);
635 if ((stateMask & LOADED) != 0)
636 control.LoadRecursive ();
638 if ((stateMask & PRERENDERED) != 0)
639 control.PreRenderRecursiveInternal ();
642 void SetNamingContainer (Control nc)
645 _namingContainer = nc;
651 protected virtual void AddParsedSubObject (object obj) //DIT
653 Control c = obj as Control;
658 [EditorBrowsable (EditorBrowsableState.Advanced)]
659 public virtual void ApplyStyleSheetSkin (Page page)
664 if (!EnableTheming) /* this enough? */
667 /* apply the style sheet skin here */
668 if (page.StyleSheetPageTheme != null) {
669 ControlSkin cs = page.StyleSheetPageTheme.GetControlSkin (GetType (), SkinID);
676 protected void BuildProfileTree (string parentId, bool calcViewState)
680 protected void ClearChildControlState ()
682 _isChildControlStateCleared = true;
685 protected void ClearChildState ()
687 ClearChildViewState ();
688 ClearChildControlState ();
691 protected void ClearChildViewState ()
696 protected internal virtual void CreateChildControls () //DIT
700 protected virtual ControlCollection CreateControlCollection () //DIT
702 return new ControlCollection (this);
705 protected virtual void EnsureChildControls ()
707 if (ChildControlsCreated == false && (stateMask & CREATING_CONTROLS) == 0) {
708 stateMask |= CREATING_CONTROLS;
710 Adapter.CreateChildControls ();
712 CreateChildControls ();
713 ChildControlsCreated = true;
714 stateMask &= ~CREATING_CONTROLS;
718 void EnsureIDInternal ()
723 _userId = NamingContainer.GetDefaultName ();
724 SetMask (AUTOID_SET, true);
727 protected void EnsureID ()
729 if (NamingContainer == null)
732 SetMask (ID_SET, true);
735 protected bool HasEvents ()
737 return _events != null;
740 void ResetControlsCache ()
742 _controlsCache = null;
744 if ((this.stateMask & IS_NAMING_CONTAINER) == 0 && Parent != null)
745 Parent.ResetControlsCache ();
748 Hashtable InitControlsCache ()
750 if (_controlsCache != null)
751 return _controlsCache;
753 if ((this.stateMask & IS_NAMING_CONTAINER) != 0 || Parent == null)
754 //LAMESPEC: MS' docs don't mention it, but FindControl is case insensitive.
755 _controlsCache = new Hashtable (StringComparer.OrdinalIgnoreCase);
757 _controlsCache = Parent.InitControlsCache ();
759 return _controlsCache;
762 void EnsureControlsCache ()
764 if (_controlsCache != null)
767 InitControlsCache ();
768 FillControlCache (Controls);
772 void FillControlCache (ControlCollection controls)
774 foreach (Control c in controls) {
776 if (c._userId != null)
777 _controlsCache.Add (c._userId, c);
778 } catch (ArgumentException) {
779 throw new HttpException (
780 "Multiple controls with the same ID '" +
782 "' were found. FindControl requires that controls have unique IDs. ");
785 if ((c.stateMask & IS_NAMING_CONTAINER) == 0 && c.HasControls ())
786 FillControlCache (c.Controls);
790 protected bool IsLiteralContent ()
792 if (HasControls () && _controls.Count == 1 && (_controls [0] is LiteralControl))
798 [WebSysDescription ("")]
799 public virtual Control FindControl (string id)
801 return FindControl (id, 0);
804 Control LookForControlByName (string id)
806 EnsureControlsCache ();
807 return (Control) _controlsCache [id];
810 protected virtual Control FindControl (string id, int pathOffset)
812 EnsureChildControls ();
813 Control namingContainer = null;
814 if ((stateMask & IS_NAMING_CONTAINER) == 0) {
815 namingContainer = NamingContainer;
816 if (namingContainer == null)
819 return namingContainer.FindControl (id, pathOffset);
825 int separatorIdx = id.IndexOf (IdSeparator, pathOffset);
826 if (separatorIdx == -1)
827 return LookForControlByName (id.Substring (pathOffset));
829 string idfound = id.Substring (pathOffset, separatorIdx - pathOffset);
830 namingContainer = LookForControlByName (idfound);
831 if (namingContainer == null)
834 return namingContainer.FindControl (id, separatorIdx + 1);
837 protected virtual void LoadViewState (object savedState)
839 if (savedState != null) {
840 ViewState.LoadViewState (savedState);
841 object o = ViewState ["Visible"];
843 SetMask (VISIBLE, (bool) o);
844 stateMask |= VISIBLE_CHANGED;
849 // [MonoTODO("Secure?")]
850 protected string MapPathSecure (string virtualPath)
852 string combined = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
853 return Context.Request.MapPath (combined);
856 protected virtual bool OnBubbleEvent (object source, EventArgs args) //DIT
859 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
860 string type_name = null;
862 type_name = GetType ().Name;
863 trace.Write ("control", String.Concat ("OnBubbleEvent ", _userId, " ", type_name));
869 protected virtual void OnDataBinding (EventArgs e)
871 if ((event_mask & databinding_mask) != 0) {
872 EventHandler eh = (EventHandler) (_events [DataBindingEvent]);
875 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
876 string type_name = null;
878 type_name = GetType ().Name;
879 trace.Write ("control", String.Concat ("OnDataBinding ", _userId, " ", type_name));
887 protected internal virtual void OnInit (EventArgs e)
889 if ((event_mask & init_mask) != 0) {
890 EventHandler eh = (EventHandler) (_events [InitEvent]);
893 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
894 string type_name = null;
896 type_name = GetType ().Name;
897 trace.Write ("control", String.Concat ("OnInit ", _userId, " ", type_name));
905 protected internal virtual void OnLoad (EventArgs e)
907 if ((event_mask & load_mask) != 0) {
908 EventHandler eh = (EventHandler) (_events [LoadEvent]);
911 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
912 string type_name = null;
914 type_name = GetType ().Name;
915 trace.Write ("control", String.Concat ("OnLoad ", _userId, " ", type_name));
923 protected internal virtual void OnPreRender (EventArgs e)
925 if ((event_mask & prerender_mask) != 0) {
926 EventHandler eh = (EventHandler) (_events [PreRenderEvent]);
929 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
930 string type_name = null;
932 type_name = GetType ().Name;
933 trace.Write ("control", String.Concat ("OnPreRender ", _userId, " ", type_name));
941 protected internal virtual void OnUnload (EventArgs e)
943 if ((event_mask & unload_mask) != 0) {
944 EventHandler eh = (EventHandler) (_events [UnloadEvent]);
947 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
948 string type_name = null;
950 type_name = GetType ().Name;
951 trace.Write ("control", String.Concat ("OnUnload ", _userId, " ", type_name));
959 protected internal Stream OpenFile (string path)
962 string filePath = Context.Server.MapPath (path);
963 return File.OpenRead (filePath);
965 catch (UnauthorizedAccessException) {
966 throw new HttpException ("Access to the specified file was denied.");
970 internal string GetPhysicalFilePath (string virtualPath)
974 if (VirtualPathUtility.IsAbsolute (virtualPath))
975 return page != null ? page.MapPath (virtualPath) : Context.Server.MapPath (virtualPath);
977 // We need to determine whether one of our parents is a
978 // master page. If so, we need to map the path
979 // relatively to the master page and not our containing
980 // page/control. This is necessary for cases when a
981 // relative path is used in a control placed in a master
982 // page and the master page is referenced from a
983 // location other than its own. In such cases MS.NET looks
984 // for the file in the directory where the master page
987 // An example of where it is needed is at
989 // http://quickstarts.asp.net/QuickStartv20/aspnet/samples/masterpages/masterpages_cs/pages/default.aspx
991 MasterPage master = null;
992 Control ctrl = Parent;
994 while (ctrl != null) {
995 if (ctrl is MasterPage) {
996 master = ctrl as MasterPage;
1004 path = VirtualPathUtility.Combine (master.TemplateSourceDirectory + "/", virtualPath);
1006 path = VirtualPathUtility.Combine (TemplateSourceDirectory + "/", virtualPath);
1008 return page != null ? page.MapPath (path) : Context.Server.MapPath (path);
1011 protected void RaiseBubbleEvent (object source, EventArgs args)
1016 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1017 string type_name = null;
1018 if (trace != null) {
1019 type_name = GetType ().Name;
1020 trace.Write ("control", String.Concat ("RaiseBubbleEvent ", _userId, " ", type_name));
1023 if (c.OnBubbleEvent (source, args)) {
1026 trace.Write ("control", String.Concat ("End RaiseBubbleEvent (false) ", _userId, " ", type_name));
1032 trace.Write ("control", String.Concat ("End RaiseBubbleEvent (true) ", _userId, " ", type_name));
1038 protected internal virtual void Render (HtmlTextWriter writer) //DIT
1040 RenderChildren (writer);
1043 protected internal virtual void RenderChildren (HtmlTextWriter writer) //DIT
1045 if (_renderMethodDelegate != null) {
1046 _renderMethodDelegate (writer, this);
1047 } else if (_controls != null) {
1048 int len = _controls.Count;
1050 for (int i = 0; i < len; i++) {
1054 ControlAdapter tmp = c.Adapter;
1056 c.RenderControl (writer, tmp);
1058 c.RenderControl (writer);
1063 protected virtual ControlAdapter ResolveAdapter ()
1065 HttpContext context = Context;
1067 if (context == null)
1070 if (!context.Request.BrowserMightHaveAdapters)
1073 // Search up the type hierarchy until we find a control with an adapter.
1074 IDictionary typeMap = context.Request.Browser.Adapters;
1075 Type controlType = GetType ();
1076 Type adapterType = (Type)typeMap [controlType];
1077 while (adapterType == null && controlType != typeof (Control)) {
1078 controlType = controlType.BaseType;
1079 adapterType = (Type)typeMap [controlType];
1082 ControlAdapter a = null;
1083 if (adapterType != null)
1084 a = (ControlAdapter)Activator.CreateInstance (adapterType);
1088 protected virtual object SaveViewState ()
1090 if ((stateMask & VISIBLE_CHANGED) != 0) {
1091 ViewState ["Visible"] = (stateMask & VISIBLE) != 0;
1092 } else if (_viewState == null) {
1096 return _viewState.SaveViewState ();
1099 protected virtual void TrackViewState ()
1101 if (_viewState != null)
1102 _viewState.TrackViewState ();
1104 stateMask |= TRACK_VIEWSTATE;
1107 public virtual void Dispose ()
1109 if ((event_mask & disposed_mask) != 0) {
1110 EventHandler eh = (EventHandler) (_events [DisposedEvent]);
1112 eh (this, EventArgs.Empty);
1116 [WebCategory ("FIXME")]
1117 [WebSysDescription ("Raised when the contols databound properties are evaluated.")]
1118 public event EventHandler DataBinding {
1120 event_mask |= databinding_mask;
1121 Events.AddHandler (DataBindingEvent, value);
1123 remove { Events.RemoveHandler (DataBindingEvent, value); }
1126 [WebSysDescription ("Raised when the contol is disposed.")]
1127 public event EventHandler Disposed {
1129 event_mask |= disposed_mask;
1130 Events.AddHandler (DisposedEvent, value);
1132 remove { Events.RemoveHandler (DisposedEvent, value); }
1135 [WebSysDescription ("Raised when the page containing the control is initialized.")]
1136 public event EventHandler Init {
1138 event_mask |= init_mask;
1139 Events.AddHandler (InitEvent, value);
1141 remove { Events.RemoveHandler (InitEvent, value); }
1144 [WebSysDescription ("Raised after the page containing the control has been loaded.")]
1145 public event EventHandler Load {
1147 event_mask |= load_mask;
1148 Events.AddHandler (LoadEvent, value);
1150 remove { Events.RemoveHandler (LoadEvent, value); }
1153 [WebSysDescription ("Raised before the page containing the control is rendered.")]
1154 public event EventHandler PreRender {
1156 event_mask |= prerender_mask;
1157 Events.AddHandler (PreRenderEvent, value);
1159 remove { Events.RemoveHandler (PreRenderEvent, value); }
1162 [WebSysDescription ("Raised when the page containing the control is unloaded.")]
1163 public event EventHandler Unload {
1165 event_mask |= unload_mask;
1166 Events.AddHandler (UnloadEvent, value);
1168 remove { Events.RemoveHandler (UnloadEvent, value); }
1171 public virtual void DataBind () //DIT
1176 protected virtual void DataBindChildren ()
1178 if (!HasControls ())
1181 int len = _controls.Count;
1182 for (int i = 0; i < len; i++) {
1183 Control c = _controls [i];
1188 public virtual bool HasControls ()
1190 return (_controls != null && _controls.Count > 0);
1193 public virtual void RenderControl (HtmlTextWriter writer)
1195 if (this.adapter != null) {
1196 RenderControl (writer, this.adapter);
1200 if ((stateMask & VISIBLE) != 0) {
1201 HttpContext ctx = Context;
1202 TraceContext trace = (ctx != null) ? ctx.Trace : null;
1204 if ((trace != null) && trace.IsEnabled)
1205 pos = ctx.Response.GetOutputByteCount ();
1208 if ((trace != null) && trace.IsEnabled) {
1209 int size = ctx.Response.GetOutputByteCount () - pos;
1210 trace.SaveSize (this, size >= 0 ? size : 0);
1215 protected void RenderControl (HtmlTextWriter writer, ControlAdapter adapter)
1217 if ((stateMask & VISIBLE) != 0) {
1218 adapter.BeginRender (writer);
1219 adapter.Render (writer);
1220 adapter.EndRender (writer);
1224 public string ResolveUrl (string relativeUrl)
1226 if (relativeUrl == null)
1227 throw new ArgumentNullException ("relativeUrl");
1229 if (relativeUrl == String.Empty)
1232 if (VirtualPathUtility.IsAbsolute (relativeUrl))
1235 if (relativeUrl [0] == '#')
1238 string ts = AppRelativeTemplateSourceDirectory;
1239 HttpContext ctx = Context;
1240 HttpResponse resp = ctx != null ? ctx.Response : null;
1241 if (ts == null || ts.Length == 0 || resp == null || relativeUrl.IndexOf (':') >= 0)
1244 if (!VirtualPathUtility.IsAppRelative (relativeUrl))
1245 relativeUrl = VirtualPathUtility.Combine (VirtualPathUtility.AppendTrailingSlash (ts), relativeUrl);
1247 return resp.ApplyAppPathModifier (relativeUrl);
1251 public string ResolveClientUrl (string relativeUrl)
1253 if (relativeUrl == null)
1254 throw new ArgumentNullException ("relativeUrl");
1256 if (relativeUrl.Length == 0)
1257 return String.Empty;
1260 relativeUrl = ResolveClientUrlInternal (relativeUrl);
1262 javax.faces.context.FacesContext faces = getFacesContext ();
1267 if (relativeUrl.IndexOf (':') >= 0)
1268 url = ResolveAppRelativeFromFullPath (relativeUrl);
1269 else if (VirtualPathUtility.IsAbsolute (relativeUrl))
1270 url = VirtualPathUtility.ToAppRelative (relativeUrl);
1272 return faces.getApplication ().getViewHandler ().getResourceURL (faces, relativeUrl);
1274 if (VirtualPathUtility.IsAppRelative (url)) {
1275 url = url.Substring (1);
1276 url = url.Length == 0 ? "/" : url;
1277 return faces.getApplication ().getViewHandler ().getResourceURL (faces, url);
1282 string ResolveClientUrlInternal (string relativeUrl) {
1283 if (relativeUrl.StartsWith (J2EE.J2EEConsts.ACTION_URL_PREFIX, StringComparison.Ordinal))
1284 return CreateActionUrl (relativeUrl.Substring (J2EE.J2EEConsts.ACTION_URL_PREFIX.Length));
1286 if (relativeUrl.StartsWith (J2EE.J2EEConsts.RENDER_URL_PREFIX, StringComparison.Ordinal))
1287 return ResolveClientUrl (relativeUrl.Substring (J2EE.J2EEConsts.RENDER_URL_PREFIX.Length));
1290 if (VirtualPathUtility.IsAbsolute (relativeUrl) || relativeUrl.IndexOf (':') >= 0)
1293 HttpContext context = Context;
1294 HttpRequest req = context != null ? context.Request : null;
1296 string templateSourceDirectory = TemplateSourceDirectory;
1297 if (templateSourceDirectory == null || templateSourceDirectory.Length == 0)
1300 string basePath = req.ClientFilePath;
1302 if (basePath.Length > 1 && basePath [basePath.Length - 1] != '/')
1303 basePath = VirtualPathUtility.GetDirectory (basePath, false);
1305 if (VirtualPathUtility.IsAppRelative (relativeUrl))
1306 return VirtualPathUtility.MakeRelative (basePath, relativeUrl);
1308 string templatePath = VirtualPathUtility.AppendTrailingSlash (templateSourceDirectory);
1310 if (basePath.Length == templatePath.Length && String.CompareOrdinal (basePath, templatePath) == 0)
1313 relativeUrl = VirtualPathUtility.Combine (templatePath, relativeUrl);
1314 return VirtualPathUtility.MakeRelative (basePath, relativeUrl);
1319 internal bool HasRenderMethodDelegate ()
1321 return _renderMethodDelegate != null;
1324 [EditorBrowsable (EditorBrowsableState.Advanced)]
1325 public void SetRenderMethodDelegate (RenderMethod renderMethod) //DIT
1327 _renderMethodDelegate = renderMethod;
1330 internal void LoadRecursive ()
1333 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1334 string type_name = null;
1335 if (trace != null) {
1336 type_name = GetType ().Name;
1337 trace.Write ("control", String.Concat ("LoadRecursive ", _userId, " ", type_name));
1340 if (Adapter != null)
1341 Adapter.OnLoad (EventArgs.Empty);
1343 OnLoad (EventArgs.Empty);
1344 if (HasControls ()) {
1345 int len = _controls.Count;
1346 for (int i = 0; i < len; i++) {
1347 Control c = _controls [i];
1354 trace.Write ("control", String.Concat ("End LoadRecursive ", _userId, " ", type_name));
1356 stateMask |= LOADED;
1359 internal void UnloadRecursive (Boolean dispose)
1362 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1363 string type_name = null;
1364 if (trace != null) {
1365 type_name = GetType ().Name;
1366 trace.Write ("control", String.Concat ("UnloadRecursive ", _userId, " ", type_name));
1369 if (HasControls ()) {
1370 int len = _controls.Count;
1371 for (int i = 0; i < len; i++) {
1372 Control c = _controls [i];
1373 c.UnloadRecursive (dispose);
1379 trace.Write ("control", String.Concat ("End UnloadRecursive ", _userId, " ", type_name));
1381 ControlAdapter tmp = Adapter;
1383 tmp.OnUnload (EventArgs.Empty);
1385 OnUnload (EventArgs.Empty);
1390 internal void PreRenderRecursiveInternal ()
1396 SetMask (VISIBLE, true);
1397 EnsureChildControls ();
1399 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1400 string type_name = null;
1401 if (trace != null) {
1402 type_name = GetType ().Name;
1403 trace.Write ("control", String.Concat ("PreRenderRecursive ", _userId, " ", type_name));
1406 if (Adapter != null)
1407 Adapter.OnPreRender (EventArgs.Empty);
1409 OnPreRender (EventArgs.Empty);
1410 if (!HasControls ())
1413 int len = _controls.Count;
1414 for (int i = 0; i < len; i++) {
1415 Control c = _controls [i];
1416 c.PreRenderRecursiveInternal ();
1420 trace.Write ("control", String.Concat ("End PreRenderRecursive ", _userId, " ", type_name));
1423 SetMask (VISIBLE, false);
1425 stateMask |= PRERENDERED;
1428 internal void InitRecursive (Control namingContainer)
1431 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1432 string type_name = null;
1433 if (trace != null) {
1434 type_name = GetType ().Name;
1435 trace.Write ("control", String.Concat ("InitRecursive ", _userId, " ", type_name));
1438 SetNamingContainer (namingContainer);
1440 if (HasControls ()) {
1441 if ((stateMask & IS_NAMING_CONTAINER) != 0)
1442 namingContainer = this;
1444 int len = _controls.Count;
1445 for (int i = 0; i < len; i++) {
1446 Control c = _controls [i];
1447 c.InitRecursive (namingContainer);
1451 if ((stateMask & REMOVED) == 0 && (stateMask & INITED) != INITED) {
1452 stateMask |= INITING;
1454 ControlAdapter tmp = Adapter;
1456 tmp.OnInit (EventArgs.Empty);
1458 OnInit (EventArgs.Empty);
1460 stateMask |= INITED;
1461 stateMask &= ~INITING;
1466 trace.Write ("control", String.Concat ("End InitRecursive ", _userId, " ", type_name));
1470 internal object SaveViewStateRecursive ()
1472 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1474 string type_name = null;
1475 if (trace != null) {
1476 type_name = GetType ().Name;
1477 trace.Write ("control", String.Concat ("SaveViewStateRecursive ", _userId, " ", type_name));
1481 ArrayList controlStates = null;
1482 bool byId = LoadViewStateByID;
1483 if (HasControls ()) {
1484 int len = _controls.Count;
1485 for (int i = 0; i < len; i++) {
1486 Control ctrl = _controls [i];
1487 object ctrlState = ctrl.SaveViewStateRecursive ();
1488 if (ctrlState == null)
1491 if (controlStates == null)
1492 controlStates = new ArrayList ();
1495 controlStates.Add (new Pair (ctrl.ID, ctrlState));
1497 controlStates.Add (new Pair (i, ctrlState));
1501 object thisAdapterViewState = null;
1502 if (Adapter != null)
1503 thisAdapterViewState = Adapter.SaveAdapterViewState ();
1505 object thisState = null;
1507 if (IsViewStateEnabled)
1508 thisState = SaveViewState ();
1510 if (thisState == null && controlStates == null) {
1511 if (trace != null) {
1513 trace.Write ("control", "End SaveViewStateRecursive " + _userId + " " + type_name + " saved nothing");
1515 trace.SaveViewState (this, null);
1520 if (trace != null) {
1522 trace.Write ("control", "End SaveViewStateRecursive " + _userId + " " + type_name + " saved a Triplet");
1524 trace.SaveViewState (this, thisState);
1526 thisState = new object[] { thisState, thisAdapterViewState };
1527 return new Pair (thisState, controlStates);
1530 internal void LoadViewStateRecursive (object savedState)
1532 if (savedState == null)
1536 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1537 string type_name = null;
1538 if (trace != null) {
1539 type_name = GetType ().Name;
1540 trace.Write ("control", String.Concat ("LoadViewStateRecursive ", _userId, " ", type_name));
1543 Pair savedInfo = (Pair) savedState;
1544 object[] controlAndAdapterViewStates = (object [])savedInfo.First;
1545 if (Adapter != null)
1546 Adapter.LoadAdapterViewState (controlAndAdapterViewStates [1]);
1547 LoadViewState (controlAndAdapterViewStates [0]);
1549 ArrayList controlStates = savedInfo.Second as ArrayList;
1550 if (controlStates == null)
1553 int nControls = controlStates.Count;
1554 bool byId = LoadViewStateByID;
1555 for (int i = 0; i < nControls; i++) {
1556 Pair p = controlStates [i] as Pair;
1561 string id = (string)p.First;
1564 foreach (Control c in Controls) {
1568 c.LoadViewStateRecursive (p.Second);
1574 if (pendingVS == null)
1575 pendingVS = new Hashtable ();
1576 pendingVS [id] = p.Second;
1579 int k = (int) p.First;
1580 if (k < Controls.Count) {
1581 Control c = Controls [k];
1582 c.LoadViewStateRecursive (p.Second);
1584 if (pendingVS == null)
1585 pendingVS = new Hashtable ();
1587 pendingVS [k] = p.Second;
1594 trace.Write ("control", String.Concat ("End LoadViewStateRecursive ", _userId, " ", type_name));
1596 stateMask |= VIEWSTATE_LOADED;
1599 internal ControlSkin controlSkin;
1601 internal void ApplyTheme ()
1604 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1605 string type_name = null;
1606 if (trace != null) {
1607 type_name = GetType ().Name;
1608 trace.Write ("control", String.Concat ("ApplyThemeRecursive ", _userId, " ", type_name));
1612 if (page != null && page.PageTheme != null && EnableTheming) {
1613 ControlSkin controlSkin = page.PageTheme.GetControlSkin (GetType (), SkinID);
1614 if (controlSkin != null)
1615 controlSkin.ApplySkin (this);
1620 trace.Write ("control", String.Concat ("End ApplyThemeRecursive ", _userId, " ", type_name));
1624 internal bool AutoID {
1625 get { return (stateMask & AUTOID) != 0; }
1627 if (value == false && (stateMask & IS_NAMING_CONTAINER) != 0)
1630 SetMask (AUTOID, value);
1634 protected internal virtual void RemovedControl (Control control)
1636 control.UnloadRecursive (false);
1637 control._parent = null;
1638 control._page = null;
1639 control._namingContainer = null;
1640 if ((control.stateMask & AUTOID_SET) != 0) {
1641 control._userId = null;
1642 control.SetMask (ID_SET, false);
1644 control.NullifyUniqueID ();
1645 control.SetMask (REMOVED, true);
1646 ResetControlsCache ();
1649 string skinId = string.Empty;
1650 bool _enableTheming = true;
1654 [DefaultValue (true)]
1655 public virtual bool EnableTheming {
1657 if ((stateMask & ENABLE_THEMING) != 0)
1658 return _enableTheming;
1660 if (_parent != null)
1661 return _parent.EnableTheming;
1666 SetMask (ENABLE_THEMING, true);
1667 _enableTheming = value;
1673 [Filterable (false)]
1674 public virtual string SkinID {
1675 get { return skinId; }
1676 set { skinId = value; }
1679 ControlBuilder IControlBuilderAccessor.ControlBuilder {
1680 get { throw new NotImplementedException (); }
1683 IDictionary IControlDesignerAccessor.GetDesignModeState ()
1685 throw new NotImplementedException ();
1688 void IControlDesignerAccessor.SetDesignModeState (IDictionary designData)
1690 SetDesignModeState (designData);
1693 void IControlDesignerAccessor.SetOwnerControl (Control control)
1695 throw new NotImplementedException ();
1698 IDictionary IControlDesignerAccessor.UserData {
1699 get { throw new NotImplementedException (); }
1702 ExpressionBindingCollection expressionBindings;
1704 ExpressionBindingCollection IExpressionsAccessor.Expressions {
1706 if (expressionBindings == null)
1707 expressionBindings = new ExpressionBindingCollection ();
1708 return expressionBindings;
1712 bool IExpressionsAccessor.HasExpressions {
1713 get { return (expressionBindings != null && expressionBindings.Count > 0); }
1716 public virtual void Focus ()
1718 Page.SetFocus (this);
1721 protected internal virtual void LoadControlState (object state)
1725 protected internal virtual object SaveControlState ()
1730 protected virtual void DataBind (bool raiseOnDataBinding)
1732 bool foundDataItem = false;
1734 if ((stateMask & IS_NAMING_CONTAINER) != 0 && Page != null) {
1735 object o = DataBinder.GetDataItem (this, out foundDataItem);
1737 Page.PushDataItemContext (o);
1741 if (raiseOnDataBinding)
1742 OnDataBinding (EventArgs.Empty);
1743 DataBindChildren ();
1746 Page.PopDataItemContext ();
1750 protected virtual IDictionary GetDesignModeState ()
1752 throw new NotImplementedException ();
1755 protected virtual void SetDesignModeState (IDictionary data)
1757 throw new NotImplementedException ();
1760 internal bool IsInited {
1761 get { return (stateMask & INITED) != 0; }
1764 internal bool IsLoaded {
1765 get { return (stateMask & LOADED) != 0; }
1768 internal bool IsPrerendered {
1769 get { return (stateMask & PRERENDERED) != 0; }
1772 bool CheckForValidationSupport ()
1774 return GetType ().GetCustomAttributes (typeof (SupportsEventValidationAttribute), false).Length > 0;
1778 // Apparently this is where .NET routes validation from all the controls which
1781 // http://odetocode.com/Blogs/scott/archive/2006/03/20/3145.aspx
1782 // Sample in here contains ValidateEvent in the stack trace
1784 // http://odetocode.com/blogs/scott/archive/2006/03/21/3153.aspx
1786 // http://www.alexthissen.nl/blogs/main/archive/2005/12/13/event-validation-of-controls-in-asp-net-2-0.aspx
1788 // It also seems that it's the control's responsibility to call this method or
1789 // validation won't take place. Also, the SupportsEventValidation attribute must be
1790 // present on the control for validation to take place.
1792 internal void ValidateEvent (String uniqueId, String argument)
1796 if (page != null && CheckForValidationSupport ())
1797 page.ClientScript.ValidateEvent (uniqueId, argument);
1800 void IParserAccessor.AddParsedSubObject (object obj)
1802 this.AddParsedSubObject (obj);
1805 DataBindingCollection IDataBindingsAccessor.DataBindings {
1807 if (dataBindings == null) {
1808 dataBindings = new DataBindingCollection ();
1810 return dataBindings;
1814 bool IDataBindingsAccessor.HasDataBindings {
1816 if (dataBindings != null && dataBindings.Count > 0) {