1 //------------------------------------------------------------------------------
2 // <copyright file="Control.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.Web.UI {
8     using System;
9     using System.Collections;
10     using System.Collections.Specialized;
11     using System.ComponentModel;
12     using System.ComponentModel.Design;
13     using System.ComponentModel.Design.Serialization;
14     using System.Diagnostics.CodeAnalysis;
15     using System.Globalization;
16     using System.IO;
17     using System.Reflection;
18     using System.Runtime.CompilerServices;
19     using System.Security.Permissions;
20     using System.Text;
21     using System.Threading.Tasks;
22     using System.Web.Caching;
23     using System.Web.Configuration;
24     using System.Web.Hosting;
25     using System.Web.Routing;
26     using System.Web.UI.Adapters;
27     using System.Web.UI.HtmlControls;
28     using System.Web.UI.WebControls;
29     using System.Web.Util;
30     using HttpException = System.Web.HttpException;
31 
32     // Delegate used for the compiled template
RenderMethod(HtmlTextWriter output, Control container)33     public delegate void RenderMethod(HtmlTextWriter output, Control container);
34 
BuildMethod()35     public delegate Control BuildMethod();
36 
37     // Defines the properties, methods, and events that are shared by all server
38     // controls in the Web Forms page framework.</para>
39     [
40     Bindable(true),
41     DefaultProperty("ID"),
42     DesignerCategory("Code"),
43     Designer("System.Web.UI.Design.ControlDesigner, " + AssemblyRef.SystemDesign),
44     DesignerSerializer("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, " + AssemblyRef.MicrosoftVisualStudioWeb,  "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + AssemblyRef.SystemDesign),
45     Themeable(false),
46     ToolboxItemFilter("System.Web.UI", ToolboxItemFilterType.Require),
47     ToolboxItemAttribute("System.Web.UI.Design.WebControlToolboxItem, " + AssemblyRef.SystemDesign)
48     ]
49     public class Control : IComponent, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor {
50 
51         internal static readonly object EventDataBinding = new object();
52         internal static readonly object EventInit = new object();
53         internal static readonly object EventLoad = new object();
54         internal static readonly object EventUnload = new object();
55         internal static readonly object EventPreRender = new object();
56         private static readonly object EventDisposed = new object();
57 
58         internal const bool EnableViewStateDefault = true;
59         internal const char ID_SEPARATOR = '$';
60         private const char ID_RENDER_SEPARATOR = '_';
61         internal const char LEGACY_ID_SEPARATOR = ':';
62 
63         private string _id;
64         // allows us to reuse the id variable to store a calculated id w/o polluting the public getter
65         private string _cachedUniqueID;
66         private string _cachedPredictableID;
67         private Control _parent;
68 
69         // fields related to being a container
70         private ControlState _controlState;
71         private StateBag _viewState;
72 
73         private EventHandlerList _events;
74         private ControlCollection _controls;
75 
76         // The naming container that this control leaves in.  Note that even if
77         // this ctrl is a naming container, it will not point to itself, but to
78         // the naming container that contains it.
79         private Control _namingContainer;
80         internal Page _page;
81         private OccasionalFields _occasionalFields;
82         // The virtual directory of the Page or UserControl that hosts this control.
83 
84         // const masks into the BitVector32
85         private const int idNotCalculated           = 0x00000001;
86         private const int marked                    = 0x00000002;
87         private const int disableViewState          = 0x00000004;
88         private const int controlsCreated           = 0x00000008;
89         private const int invisible                 = 0x00000010;
90         private const int visibleDirty              = 0x00000020;
91         private const int idNotRequired             = 0x00000040;
92         private const int isNamingContainer         = 0x00000080;
93         private const int creatingControls          = 0x00000100;
94         private const int notVisibleOnPage          = 0x00000200;
95         private const int themeApplied              = 0x00000400;
96         private const int mustRenderID              = 0x00000800;
97         private const int disableTheming            = 0x00001000;
98         private const int enableThemingSet          = 0x00002000;
99         private const int styleSheetApplied         = 0x00004000;
100         private const int controlAdapterResolved    = 0x00008000;
101         private const int designMode                = 0x00010000;
102         private const int designModeChecked         = 0x00020000;
103         private const int disableChildControlState  = 0x00040000;
104         internal const int isWebControlDisabled     = 0x00080000;
105         private const int controlStateApplied       = 0x00100000;
106         private const int useGeneratedID            = 0x00200000;
107         private const int validateRequestModeDirty  = 0x00400000;
108         private const int viewStateNotInherited     = 0x00800000;
109         private const int viewStateMode             = 0x01000000;
110         private const int clientIDMode              = 0x06000000;
111         private const int clientIDModeOffset        = 25;
112         private const int effectiveClientIDMode     = 0x18000000;
113         private const int effectiveClientIDModeOffset = 27;
114         private const int validateRequestMode       = 0x60000000;
115         private const int validateRequestModeOffset = 29;
116         #pragma warning disable 0649
117         internal SimpleBitVector32 flags;
118         #pragma warning restore 0649
119 
120         private const string automaticIDPrefix = "ctl";
121         private const string automaticLegacyIDPrefix = "_ctl";
122         private const int automaticIDCount = 128;
123         private static readonly string[] automaticIDs = new string [automaticIDCount] {
124             "ctl00", "ctl01", "ctl02", "ctl03", "ctl04", "ctl05", "ctl06",
125             "ctl07", "ctl08", "ctl09", "ctl10", "ctl11", "ctl12", "ctl13",
126             "ctl14", "ctl15", "ctl16", "ctl17", "ctl18", "ctl19", "ctl20",
127             "ctl21", "ctl22", "ctl23", "ctl24", "ctl25", "ctl26", "ctl27",
128             "ctl28", "ctl29", "ctl30", "ctl31", "ctl32", "ctl33", "ctl34",
129             "ctl35", "ctl36", "ctl37", "ctl38", "ctl39", "ctl40", "ctl41",
130             "ctl42", "ctl43", "ctl44", "ctl45", "ctl46", "ctl47", "ctl48",
131             "ctl49", "ctl50", "ctl51", "ctl52", "ctl53", "ctl54", "ctl55",
132             "ctl56", "ctl57", "ctl58", "ctl59", "ctl60", "ctl61", "ctl62",
133             "ctl63", "ctl64", "ctl65", "ctl66", "ctl67", "ctl68", "ctl69",
134             "ctl70", "ctl71", "ctl72", "ctl73", "ctl74", "ctl75", "ctl76",
135             "ctl77", "ctl78", "ctl79", "ctl80", "ctl81", "ctl82", "ctl83",
136             "ctl84", "ctl85", "ctl86", "ctl87", "ctl88", "ctl89", "ctl90",
137             "ctl91", "ctl92", "ctl93", "ctl94", "ctl95", "ctl96", "ctl97",
138             "ctl98", "ctl99",
139             "ctl100", "ctl101", "ctl102", "ctl103", "ctl104", "ctl105", "ctl106",
140             "ctl107", "ctl108", "ctl109", "ctl110", "ctl111", "ctl112", "ctl113",
141             "ctl114", "ctl115", "ctl116", "ctl117", "ctl118", "ctl119", "ctl120",
142             "ctl121", "ctl122", "ctl123", "ctl124", "ctl125", "ctl126", "ctl127"
143 
144         };
145 
146         /// <devdoc>
147         /// <para>Initializes a new instance of the <see cref='System.Web.UI.Control'/> class.</para>
148         /// </devdoc>
Control()149         public Control() {
150             if (this is INamingContainer)
151                 flags.Set(isNamingContainer);
152         }
153 
154         private ClientIDMode ClientIDModeValue {
155             get {
156                 return (ClientIDMode)flags[clientIDMode, clientIDModeOffset];
157             }
158             set {
159                 flags[clientIDMode, clientIDModeOffset] = (int)value;
160             }
161         }
162 
163         [SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId="Member")]
164         [
165         DefaultValue(ClientIDMode.Inherit),
166         Themeable(false),
167         WebCategory("Behavior"),
168         WebSysDescription(SR.Control_ClientIDMode)
169         ]
170         public virtual ClientIDMode ClientIDMode {
171             get {
172                 return ClientIDModeValue;
173             }
174             set {
175                 if (ClientIDModeValue != value) {
176                     if (value != EffectiveClientIDModeValue) {
177                         ClearEffectiveClientIDMode();
178                         ClearCachedClientID();
179                     }
180                     ClientIDModeValue = value;
181                 }
182             }
183         }
184 
185         private ClientIDMode EffectiveClientIDModeValue {
186             get {
187                 return (ClientIDMode)flags[effectiveClientIDMode, effectiveClientIDModeOffset];
188             }
189             set {
190                 flags[effectiveClientIDMode, effectiveClientIDModeOffset] = (int)value;
191             }
192         }
193 
194         internal virtual ClientIDMode EffectiveClientIDMode {
195             get {
196                 if (EffectiveClientIDModeValue == ClientIDMode.Inherit) {
197                     EffectiveClientIDModeValue = ClientIDMode;
198                     if (EffectiveClientIDModeValue == ClientIDMode.Inherit) {
199                         if (NamingContainer != null) {
200                             EffectiveClientIDModeValue = NamingContainer.EffectiveClientIDMode;
201                         }
202                         else {
203                             HttpContext context = Context;
204                             if (context != null) {
205                                 EffectiveClientIDModeValue = RuntimeConfig.GetConfig(context).Pages.ClientIDMode;
206                             }
207                             else {
208                                 EffectiveClientIDModeValue = RuntimeConfig.GetConfig().Pages.ClientIDMode;
209                             }
210                         }
211                     }
212                 }
213                 return EffectiveClientIDModeValue;
214             }
215         }
216 
217         internal string UniqueClientID {
218             get {
219                 string uniqueID = UniqueID;
220                 if(uniqueID != null && uniqueID.IndexOf(IdSeparator) >= 0) {
221                     return uniqueID.Replace(IdSeparator, ID_RENDER_SEPARATOR);
222                 }
223                 return uniqueID;
224             }
225         }
226 
227         internal string StaticClientID {
228             get {
229                 return flags[useGeneratedID] ? String.Empty : ID ?? String.Empty;
230             }
231         }
232 
233         internal ControlAdapter AdapterInternal {
234             get {
235                 if (_occasionalFields == null ||
236                     _occasionalFields.RareFields == null ||
237                     _occasionalFields.RareFields.Adapter == null) {
238                         return null;
239                 }
240                 return _occasionalFields.RareFields.Adapter;
241             }
242             set {
243                 if (value != null) {
244                     RareFieldsEnsured.Adapter = value;
245                 }
246                 else {
247                     if (_occasionalFields != null &&
248                         _occasionalFields.RareFields != null &&
249                         _occasionalFields.RareFields.Adapter != null) {
250                             _occasionalFields.RareFields.Adapter = null;
251                     }
252                 }
253             }
254         }
255 
GetClientID()256         private string GetClientID() {
257             switch (EffectiveClientIDMode) {
258                 case ClientIDMode.Predictable:
259                     return PredictableClientID;
260                 case ClientIDMode.Static:
261                     return StaticClientID;
262                 default:
263                     return UniqueClientID;
264             }
265         }
266 
GetPredictableClientIDPrefix()267         private string GetPredictableClientIDPrefix() {
268             string predictableIDPrefix;
269 
270             Control namingContainer = NamingContainer;
271             if (namingContainer != null) {
272                 if (_id == null) {
273                     GenerateAutomaticID();
274                 }
275                 if (namingContainer is Page || namingContainer is MasterPage) {
276                     predictableIDPrefix = _id;
277                 }
278                 else {
279                     predictableIDPrefix = namingContainer.GetClientID();
280                     if (String.IsNullOrEmpty(predictableIDPrefix)) {
281                         predictableIDPrefix = _id;
282                     }
283                     else {
284                         if (!String.IsNullOrEmpty(_id) && (!(this is IDataItemContainer) || (this is IDataBoundItemControl))) {
285                             predictableIDPrefix = predictableIDPrefix + ID_RENDER_SEPARATOR + _id;
286                         }
287                     }
288                 }
289             }
290             else {
291                 predictableIDPrefix = _id;
292             }
293             return predictableIDPrefix;
294         }
295 
GetPredictableClientIDSuffix()296         private string GetPredictableClientIDSuffix() {
297             string predictableIDSuffix = null;
298 
299             Control dataItemContainer = DataItemContainer;
300             if (dataItemContainer != null &&
301                 !(dataItemContainer is IDataBoundItemControl) &&
302                 (!(this is IDataItemContainer) || (this is IDataBoundItemControl))) {
303                 Control dataKeysContainer = dataItemContainer.DataKeysContainer;
304                 if (dataKeysContainer != null && (((IDataKeysControl)dataKeysContainer).ClientIDRowSuffix != null) && (((IDataKeysControl)dataKeysContainer).ClientIDRowSuffix.Length > 0)) {
305                     predictableIDSuffix = String.Empty;
306                     IOrderedDictionary dataKey = ((IDataKeysControl)dataKeysContainer).ClientIDRowSuffixDataKeys[((IDataItemContainer)dataItemContainer).DisplayIndex].Values;
307                     foreach (string suffixName in ((IDataKeysControl)dataKeysContainer).ClientIDRowSuffix) {
308                         predictableIDSuffix = predictableIDSuffix + ID_RENDER_SEPARATOR + dataKey[suffixName].ToString();
309                     }
310                 }
311                 else {
312                     int index = ((IDataItemContainer)dataItemContainer).DisplayIndex;
313                     if (index >= 0) {
314                         predictableIDSuffix = ID_RENDER_SEPARATOR + index.ToString(CultureInfo.InvariantCulture);
315                     }
316                 }
317             }
318             return predictableIDSuffix;
319         }
320 
321         internal string PredictableClientID {
322             get {
323                 if (_cachedPredictableID != null) {
324                     return _cachedPredictableID;
325                 }
326 
327                 _cachedPredictableID = GetPredictableClientIDPrefix();
328                 string suffixID = GetPredictableClientIDSuffix();
329 
330                 // Concatenates Predictable clientID and ClientIDRowSuffix if available
331                 if (!String.IsNullOrEmpty(suffixID)) {
332                     if (!String.IsNullOrEmpty(_cachedPredictableID)) {
333                         _cachedPredictableID = _cachedPredictableID + suffixID;
334                     }
335                     else {
336                         _cachedPredictableID = suffixID.Substring(1);
337                     }
338                 }
339                 return String.IsNullOrEmpty(_cachedPredictableID) ? String.Empty : _cachedPredictableID;
340             }
341         }
342 
343         /// <devdoc>
344         ///    <para>Indicates the control identifier generated by the ASP.NET framework. </para>
345         /// </devdoc>
346         [
347         Browsable(false),
348         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
349         WebSysDescription(SR.Control_ClientID)
350         ]
351         public virtual string ClientID {
352             // This property is required to render a unique client-friendly id.
353             get {
354                 if (EffectiveClientIDMode != ClientIDMode.Static) {
355                     // Ensure that ID is set. The assumption being made is that the caller
356                     // is likely to use the client ID in script, and to support that the
357                     // control should render out an ID attribute
358                     EnsureID();
359                 }
360                 return GetClientID();
361             }
362         }
363 
364         protected char ClientIDSeparator {
365             get {
366                 return ID_RENDER_SEPARATOR;
367             }
368         }
369 
370         /// <devdoc>
371         ///    <para>[To be supplied.]</para>
372         /// </devdoc>
373         [
374         WebSysDescription(SR.Control_OnDisposed)
375         ]
376         public event EventHandler Disposed {
377             add {
378                 Events.AddHandler(EventDisposed, value);
379             }
380             remove {
381                 Events.RemoveHandler(EventDisposed, value);
382             }
383         }
384 
385         /// <devdoc>
386         /// <para>Gets the <see langword='HttpContext'/> object of the current Web request. If
387         ///    the control's context is <see langword='null'/>, this will be the context of the
388         ///    control's parent, unless the parent control's context is <see langword='null'/>.
389         ///    If this is the case, this will be equal to the HttpContext property.</para>
390         /// </devdoc>
391         [
392         Browsable(false),
393         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
394         ]
395         protected internal virtual HttpContext Context {
396             //  Request context containing the intrinsics
397             get {
398                 Page page = Page;
399                 if(page != null) {
400                     return page.Context;
401                 }
402                 return HttpContext.Current;
403             }
404         }
405 
ResolveAdapter()406         protected virtual ControlAdapter ResolveAdapter() {
407             if(flags[controlAdapterResolved]) {
408                 return AdapterInternal;
409             }
410             if (DesignMode) {
411                 flags.Set(controlAdapterResolved);
412                 return null;
413             }
414 
415             HttpContext context = Context;
416             if (context != null && context.Request.Browser != null) {
417                 AdapterInternal = context.Request.Browser.GetAdapter(this);
418             }
419             flags.Set(controlAdapterResolved);
420             return AdapterInternal;
421         }
422 
423         /// <devdoc>
424         ///    <para>Indicates the list of event handler delegates for the control. This property
425         ///       is read-only.</para>
426         /// </devdoc>
427         protected ControlAdapter Adapter {
428             get {
429                 if(flags[controlAdapterResolved]) {
430                     return AdapterInternal;
431                 }
432                 AdapterInternal = ResolveAdapter();
433                 flags.Set(controlAdapterResolved);
434                 return AdapterInternal;
435             }
436         }
437 
438         /// <devdoc>
439         /// Indicates whether a control is being used in the context of a design surface.
440         /// </devdoc>
441         protected internal bool DesignMode {
442             get {
443                 if(!flags[designModeChecked]) {
444                     Page page = Page;
445                     if(page != null )  {
446                         if(page.GetDesignModeInternal()) {
447                             flags.Set(designMode);
448                         }
449                         else {
450                             flags.Clear(designMode);
451                         }
452                     }
453                     else {
454                         if(Site != null) {
455                             if(Site.DesignMode) {
456                                 flags.Set(designMode);
457                             }
458                             else {
459                                 flags.Clear(designMode);
460                             }
461                         }
462                         else if (Parent != null) {
463                             if(Parent.DesignMode) {
464                                 flags.Set(designMode);
465                             }
466 
467                             // VSWhidbey 535747: If Page, Site and Parent are all null, do not change the
468                             // designMode flag since it might had been previously set by the controlBuilder.
469                             // This does not affect runtime since designMode is by-default false.
470                             /*
471                             else {
472                                 flags.Clear(designMode);
473                             }
474                             */
475                         }
476                     }
477                     flags.Set(designModeChecked);
478                 }
479                 return flags[designMode];
480 
481             }
482         }
483 
484         // Helper function to call validateEvent.
ValidateEvent(string uniqueID)485         internal void ValidateEvent(string uniqueID) {
486             ValidateEvent(uniqueID, String.Empty);
487         }
488 
489         // Helper function to call validateEvent.
ValidateEvent(string uniqueID, string eventArgument)490         internal void ValidateEvent(string uniqueID, string eventArgument) {
491             if (Page != null && SupportsEventValidation) {
492                 Page.ClientScript.ValidateEvent(uniqueID, eventArgument);
493             }
494         }
495 
496         // Indicates whether the control supports event validation
497         // By default, all web controls in System.Web assembly supports it but not custom controls.
498         private bool SupportsEventValidation {
499             get {
500                 return SupportsEventValidationAttribute.SupportsEventValidation(this.GetType());
501             }
502         }
503 
504         /// <devdoc>
505         ///    <para>Indicates the list of event handler delegates for the control. This property
506         ///       is read-only.</para>
507         /// </devdoc>
508         protected EventHandlerList Events {
509             get {
510                 if (_events == null) {
511                     _events = new EventHandlerList();
512                 }
513                 return _events;
514             }
515         }
516 
HasEvents()517         protected bool HasEvents() {
518             return (_events != null);
519         }
520 
521         /// <devdoc>
522         ///    <para> Gets or sets the identifier for the control. Setting the
523         ///       property on a control allows programmatic access to the control's properties. If
524         ///       this property is not specified on a control, either declaratively or
525         ///       programmatically, then you cannot write event handlers and the like for the control.</para>
526         /// </devdoc>
527         [
528         ParenthesizePropertyName(true),
529         MergableProperty(false),
530         Filterable(false),
531         Themeable(false),
532         WebSysDescription(SR.Control_ID)
533         ]
534         public virtual string ID {
535             get {
536                 if (!flags[idNotCalculated] && !flags[mustRenderID]) {
537                     return null;
538                 }
539                 return _id;
540             }
541             set {
542                 // allow the id to be unset
543                 if (value != null && value.Length == 0)
544                     value = null;
545 
546                 string oldID = _id;
547 
548                 _id = value;
549                 ClearCachedUniqueIDRecursive();
550                 flags.Set(idNotCalculated);
551                 flags.Clear(useGeneratedID);
552 
553                 // Update the ID in the naming container
554                 if ((_namingContainer != null) && (oldID != null)) {
555                     _namingContainer.DirtyNameTable();
556                 }
557 
558                 if (oldID != null && oldID != _id) {
559                     ClearCachedClientID();
560                 }
561             }
562         }
563 
564 
565         /// <devdoc>
566         ///    <para>Gets and sets a value indicating whether theme is enabled.</para>
567         /// </devdoc>
568         [
569         Browsable(false),
570         DefaultValue(true),
571         Themeable(false),
572         WebCategory("Behavior"),
573         WebSysDescription(SR.Control_EnableTheming)
574         ]
575         public virtual bool EnableTheming {
576             get {
577                 if (flags[enableThemingSet]) {
578                     return !flags[disableTheming];
579                 }
580 
581                 if (Parent != null) {
582                     return Parent.EnableTheming;
583                 }
584 
585                 return !flags[disableTheming];
586             }
587             set {
588                 if ((_controlState >= ControlState.FrameworkInitialized) && !DesignMode) {
589                     throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePreInitOrAddToControls, "EnableTheming"));
590                 }
591 
592                 if(!value) {
593                     flags.Set(disableTheming);
594                 }
595                 else {
596                     flags.Clear(disableTheming);
597                 }
598 
599                 flags.Set(enableThemingSet);
600             }
601         }
602 
603         // Serialzie the value if it's set explicitely.
ShouldSerializeEnableTheming()604         internal bool ShouldSerializeEnableTheming() {
605             return flags[enableThemingSet];;
606         }
607 
608         internal bool IsBindingContainer {
609             get {
610                 return this is INamingContainer && !(this is INonBindingContainer);
611             }
612         }
613 
614         protected internal bool IsChildControlStateCleared {
615             get {
616                 return flags[disableChildControlState];
617             }
618         }
619 
620 
621         /// <devdoc>
622         ///    <para>Gets and sets the skinID of the control.</para>
623         /// </devdoc>
624         [
625         Browsable(false),
626         DefaultValue(""),
627         Filterable(false),
628         WebCategory("Behavior"),
629         WebSysDescription(SR.Control_SkinId),
630         ]
631         public virtual string SkinID {
632             get {
633                 if(_occasionalFields != null) {
634                     return _occasionalFields.SkinId == null ? String.Empty : _occasionalFields.SkinId;
635                 }
636                 return String.Empty;
637             }
638             set {
639                 if (!DesignMode) {
640                     if (flags[styleSheetApplied]) {
641                         throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforeStyleSheetApplied, "SkinId"));
642                     }
643 
644                     if (_controlState >= ControlState.FrameworkInitialized) {
645                         throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePreInitOrAddToControls, "SkinId"));
646                     }
647                 }
648 
649                 EnsureOccasionalFields();
650                 _occasionalFields.SkinId = value;
651             }
652         }
653 
654         private ControlRareFields RareFieldsEnsured {
655             get {
656                 EnsureOccasionalFields();
657                 ControlRareFields rareFields = _occasionalFields.RareFields;
658                 if(rareFields == null) {
659                     rareFields = new ControlRareFields();
660                     _occasionalFields.RareFields = rareFields;
661                 }
662 
663                 return rareFields;
664             }
665         }
666 
667         private ControlRareFields RareFields {
668             get {
669                 if(_occasionalFields != null) {
670                     return _occasionalFields.RareFields;
671                 }
672                 return null;
673             }
674         }
675 
EnsureOccasionalFields()676         private void EnsureOccasionalFields() {
677             if(_occasionalFields == null) {
678                 _occasionalFields = new OccasionalFields();
679             }
680         }
681 
682 
683         /// <devdoc>
684         ///    <para>
685         ///       Gets or sets a value indicating whether the control should maintain its view
686         ///       state, and the view state of any child control in contains, when the current
687         ///       page request ends.
688         ///    </para>
689         /// </devdoc>
690         [
691         DefaultValue(EnableViewStateDefault),
692         Themeable(false),
693         WebCategory("Behavior"),
694         WebSysDescription(SR.Control_MaintainState)
695         ]
696         public virtual bool EnableViewState {
697             get {
698                 return !flags[disableViewState];
699             }
700             set {
701                 SetEnableViewStateInternal(value);
702             }
703         }
704 
705         [
706         DefaultValue(ViewStateMode.Inherit),
707         Themeable(false),
708         WebCategory("Behavior"),
709         WebSysDescription(SR.Control_ViewStateMode)
710         ]
711         public virtual ViewStateMode ViewStateMode {
712             get {
713                 return flags[viewStateNotInherited] ?
714                     (flags[viewStateMode] ? ViewStateMode.Enabled : ViewStateMode.Disabled) :
715                     ViewStateMode.Inherit;
716             }
717             set {
718                 if ((value < ViewStateMode.Inherit) || (value > ViewStateMode.Disabled)) {
719                     throw new ArgumentOutOfRangeException("value");
720                 }
721                 if (value == ViewStateMode.Inherit) {
722                     flags.Clear(viewStateNotInherited);
723                 }
724                 else {
725                     flags.Set(viewStateNotInherited);
726                     if (value == ViewStateMode.Enabled) {
727                         flags.Set(viewStateMode);
728                     }
729                     else {
730                         flags.Clear(viewStateMode);
731                     }
732                 }
733             }
734         }
735 
736 
SetEnableViewStateInternal(bool value)737         internal void SetEnableViewStateInternal(bool value) {
738             if (!value)
739                 flags.Set(disableViewState);
740             else
741                 flags.Clear(disableViewState);
742         }
743 
744 
745         /// <devdoc>
746         /// Gets a value indicating whether the control is maintaining its view
747         /// state, when the current page request ends by looking at its own EnableViewState
748         /// value, and the value for all its parents.
749         /// </devdoc>
750         protected internal bool IsViewStateEnabled {
751             get {
752                 Control current = this;
753                 while (current != null) {
754                     if (current.EnableViewState == false) {
755                         return false;
756                     }
757                     ViewStateMode mode = current.ViewStateMode;
758                     if (mode != ViewStateMode.Inherit) {
759                         return (mode == ViewStateMode.Enabled);
760                     }
761                     current = current.Parent;
762                 }
763                 return true;
764             }
765         }
766 
767 
768         /// <devdoc>
769         ///    <para>Gets the reference to the current control's naming container.</para>
770         /// </devdoc>
771         [
772         Bindable(false),
773         Browsable(false),
774         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
775         WebSysDescription(SR.Control_NamingContainer)
776         ]
777         public virtual Control NamingContainer {
778             get {
779                 if (_namingContainer == null) {
780                     if (Parent != null) {
781                         // Search for the closest naming container in the tree
782                         if (Parent.flags[isNamingContainer])
783                             _namingContainer = Parent;
784                         else
785                             _namingContainer = Parent.NamingContainer;
786                     }
787                 }
788 
789                 return _namingContainer;
790             }
791         }
792 
793         /// <internalonly/>
794         /// <devdoc>
795         ///    <para>Returns the databinding container of this control.  In most cases,
796         ///     this is the same as the NamingContainer. But when using LoadTemplate(),
797         ///     we get into a situation where that is not the case (ASURT 94138)</para>
798         ///     The behavior is different than V1 that Usercontrol.BindingContainer is no
799         ///     longer the UserControl but the control contains it. The behavior is consistent
800         ///     with LoadTemplate() case.
801         /// </devdoc>
802         [
803         Bindable(false),
804         Browsable(false),
805         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
806         EditorBrowsable(EditorBrowsableState.Never)
807         ]
808         public Control BindingContainer {
809             get {
810                 Control bindingContainer = NamingContainer;
811                 while (bindingContainer is INonBindingContainer) {
812                     bindingContainer = bindingContainer.BindingContainer;
813                 }
814 
815                 return bindingContainer;
816             }
817         }
818 
819         [
820         Bindable(false),
821         Browsable(false),
822         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
823         EditorBrowsable(EditorBrowsableState.Never)
824         ]
825         public Control DataItemContainer {
826             get {
827                 Control dataItemContainer = NamingContainer;
828                 while (dataItemContainer != null && !(dataItemContainer is IDataItemContainer)) {
829                     dataItemContainer = dataItemContainer.DataItemContainer;
830                 }
831 
832                 return dataItemContainer;
833             }
834         }
835 
836         [
837         Bindable(false),
838         Browsable(false),
839         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
840         EditorBrowsable(EditorBrowsableState.Never)
841         ]
842         public Control DataKeysContainer {
843             get {
844                 Control dataKeysContainer = NamingContainer;
845                 while (dataKeysContainer != null && !(dataKeysContainer is IDataKeysControl)) {
846                     dataKeysContainer = dataKeysContainer.DataKeysContainer;
847                 }
848 
849                 return dataKeysContainer;
850             }
851         }
852 
853 
854 
855         /// <internalonly/>
856         /// <devdoc>
857         /// VSWhidbey 80467: Need to adapt id separator.
858         /// </devdoc>
859         protected char IdSeparator {
860             get {
861                 if (Page != null) {
862                     return Page.IdSeparator;
863                 }
864                 return IdSeparatorFromConfig;
865             }
866         }
867 
868         // VSWhidbey 475945: Use the old id separator if configured
869         internal char IdSeparatorFromConfig {
870             get {
871                 return ((EnableLegacyRendering) ? LEGACY_ID_SEPARATOR : ID_SEPARATOR);
872             }
873         }
874 
875         // VSWhidbey 244374: Allow controls to opt into loading view state by ID instead of index (perf hit)
876         protected bool LoadViewStateByID {
877             get {
878                 return ViewStateModeByIdAttribute.IsEnabled(GetType());
879             }
880         }
881 
882         /// <devdoc>
883         /// <para> Gets the <see cref='System.Web.UI.Page'/> object that contains the
884         ///    current control.</para>
885         /// </devdoc>
886         [
887         Bindable(false),
888         Browsable(false),
889         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
890         WebSysDescription(SR.Control_Page)
891         ]
892         public virtual Page Page {
893             get {
894                 if (_page == null) {
895                     if (Parent != null) {
896                         _page = Parent.Page;
897                     }
898                 }
899                 return _page;
900             }
901 
902             set {
903                 if (OwnerControl != null) {
904                     throw new InvalidOperationException();
905                 }
906                 // This is necessary because we need to set the page in generated
907                 // code before controls are added to the tree (ASURT 75330)
908                 Debug.Assert(_page == null);
909                 Debug.Assert(Parent == null || Parent.Page == null);
910                 _page = value;
911             }
912         }
913 
914         internal RouteCollection RouteCollection {
915             get {
916                 if (_occasionalFields == null ||
917                     _occasionalFields.RareFields == null ||
918                     _occasionalFields.RareFields.RouteCollection == null) {
919                         return RouteTable.Routes;
920                 }
921                 return _occasionalFields.RareFields.RouteCollection;
922             }
923             set {
924                 if (value != null) {
925                     RareFieldsEnsured.RouteCollection = value;
926                 }
927                 else {
928                     if (_occasionalFields != null &&
929                         _occasionalFields.RareFields != null &&
930                         _occasionalFields.RareFields.RouteCollection != null) {
931                             _occasionalFields.RareFields.RouteCollection = null;
932                     }
933                 }
934             }
935         }
936 
937         // VSWhidbey 244999
938         internal virtual bool IsReloadable {
939             get {
940                 return false;
941             }
942         }
943 
944         // DevDiv 33149, 43258: A backward compat. switch for Everett rendering
945         internal bool EnableLegacyRendering {
946             get {
947                 Page page = Page;
948                 if (page != null) {
949                     return (page.XhtmlConformanceMode == XhtmlConformanceMode.Legacy);
950                 }
951                 else if (DesignMode || Adapter != null) {
952                     return false;
953                 }
954                 else {
955                     return (GetXhtmlConformanceSection().Mode == XhtmlConformanceMode.Legacy);
956                 }
957             }
958         }
959 
GetXhtmlConformanceSection()960         internal XhtmlConformanceSection GetXhtmlConformanceSection() {
961             HttpContext context = Context;
962             XhtmlConformanceSection xhtmlConformanceSection;
963             if (context != null) {
964                 // if context is available, use the most efficient way to get the section
965                 xhtmlConformanceSection = RuntimeConfig.GetConfig(context).XhtmlConformance;
966             }
967             else {
968                 xhtmlConformanceSection = RuntimeConfig.GetConfig().XhtmlConformance;
969             }
970             Debug.Assert(xhtmlConformanceSection != null);
971             return xhtmlConformanceSection;
972         }
973 
974         [
975         Bindable(false),
976         Browsable(false),
977         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
978         ]
979         public virtual Version RenderingCompatibility {
980             get {
981                 if (_occasionalFields == null ||
982                     _occasionalFields.RareFields == null ||
983                     _occasionalFields.RareFields.RenderingCompatibility == null) {
984                         return RuntimeConfig.Pages.ControlRenderingCompatibilityVersion;
985                 }
986                 return _occasionalFields.RareFields.RenderingCompatibility;
987             }
988             set {
989                 if (value != null) {
990                     RareFieldsEnsured.RenderingCompatibility = value;
991                 }
992                 else {
993                     if (_occasionalFields != null &&
994                         _occasionalFields.RareFields != null &&
995                         _occasionalFields.RareFields.RenderingCompatibility != null) {
996                             _occasionalFields.RareFields.RenderingCompatibility = null;
997                     }
998                 }
999             }
1000         }
1001 
1002         private RuntimeConfig RuntimeConfig {
1003             get {
1004                 HttpContext context = Context;
1005                 if (context != null) {
1006                     // if context is available, use the most efficient way to get the config
1007                     return RuntimeConfig.GetConfig(context);
1008                 } else {
1009                     return RuntimeConfig.GetConfig();
1010                 }
1011             }
1012         }
1013 
1014         [SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings",
1015             Justification = "Consistent with other URL properties in ASP.NET.")]
GetRouteUrl(object routeParameters)1016         public string GetRouteUrl(object routeParameters) {
1017             return GetRouteUrl(new RouteValueDictionary(routeParameters));
1018         }
1019 
1020         [SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings",
1021             Justification = "Consistent with other URL properties in ASP.NET.")]
GetRouteUrl(string routeName, object routeParameters)1022         public string GetRouteUrl(string routeName, object routeParameters) {
1023             return GetRouteUrl(routeName, new RouteValueDictionary(routeParameters));
1024         }
1025 
1026         [SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings",
1027             Justification = "Consistent with other URL properties in ASP.NET.")]
GetRouteUrl(RouteValueDictionary routeParameters)1028         public string GetRouteUrl(RouteValueDictionary routeParameters) {
1029             return GetRouteUrl(null, routeParameters);
1030         }
1031 
1032         [SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings",
1033             Justification = "Consistent with other URL properties in ASP.NET.")]
GetRouteUrl(string routeName, RouteValueDictionary routeParameters)1034         public string GetRouteUrl(string routeName, RouteValueDictionary routeParameters) {
1035             VirtualPathData data = RouteCollection.GetVirtualPath(Context.Request.RequestContext, routeName, routeParameters);
1036             if (data != null) {
1037                 return data.VirtualPath;
1038             }
1039             return null;
1040         }
1041 
1042         /// <devdoc>
1043         ///    <para>Gets the reference to the <see cref='System.Web.UI.TemplateControl'/>
1044         ///    that hosts the control.</para>
1045         /// </devdoc>
GetTemplateControl()1046         internal virtual TemplateControl GetTemplateControl() {
1047             if (_occasionalFields == null || _occasionalFields.TemplateControl == null) {
1048                 if (Parent != null) {
1049                     TemplateControl templateControl = Parent.GetTemplateControl();
1050                     if (templateControl != null) {
1051                         EnsureOccasionalFields();
1052                         _occasionalFields.TemplateControl = templateControl;
1053                     }
1054                 }
1055             }
1056             return (_occasionalFields != null) ? _occasionalFields.TemplateControl : null;
1057         }
1058 
1059 
1060         /// <devdoc>
1061         ///    <para>Gets the reference to the <see cref='System.Web.UI.TemplateControl'/>
1062         ///    that hosts the control.</para>
1063         /// </devdoc>
1064         [
1065         Bindable(false),
1066         Browsable(false),
1067         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1068         WebSysDescription(SR.Control_TemplateControl)
1069         ]
1070         public TemplateControl TemplateControl {
1071             get {
1072                 return GetTemplateControl();
1073             }
1074 
1075             [EditorBrowsable(EditorBrowsableState.Never)]
1076             set {
1077                 // This setter is necessary so that controls inside templates are based on
1078                 // hosting pages not where the templates are used.
1079                 if (value != null) {
1080                     EnsureOccasionalFields();
1081                     _occasionalFields.TemplateControl = value;
1082                 }
1083                 else {
1084                     if (_occasionalFields != null &&
1085                         _occasionalFields.TemplateControl != null) {
1086                             _occasionalFields.TemplateControl = null;
1087                     }
1088                 }
1089             }
1090         }
1091 
1092         /*
1093          * Determine whether this control is a descendent of the passed in control
1094          */
IsDescendentOf(Control ancestor)1095         internal bool IsDescendentOf(Control ancestor) {
1096             Control current = this;
1097             while (current != ancestor && current.Parent != null) {
1098                 current = current.Parent;
1099             }
1100             return (current == ancestor);
1101         }
1102 
1103 
1104         /// <devdoc>
1105         ///    <para> Gets the current control's parent control in the UI hierarchy.</para>
1106         /// </devdoc>
1107         [
1108         Bindable(false),
1109         Browsable(false),
1110         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1111         WebSysDescription(SR.Control_Parent)
1112         ]
1113         public virtual Control Parent {
1114             get {
1115                 return _parent;
1116             }
1117         }
1118 
1119         internal bool IsParentedToUpdatePanel {
1120             get {
1121                 Control parent = Parent;
1122                 while (parent != null) {
1123                     if (parent is IUpdatePanel) {
1124                         return true;
1125                     }
1126                     parent = parent.Parent;
1127                 }
1128                 return false;
1129             }
1130         }
1131 
1132         /// <devdoc>
1133         ///    <para> Gets the virtual directory of the Page or UserControl that contains this control.</para>
1134         /// </devdoc>
1135         [
1136         Browsable(false),
1137         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1138         WebSysDescription(SR.Control_TemplateSourceDirectory)
1139         ]
1140         public virtual string TemplateSourceDirectory {
1141             get {
1142                 if (TemplateControlVirtualDirectory == null)
1143                     return String.Empty;
1144 
1145                 return TemplateControlVirtualDirectory.VirtualPathStringNoTrailingSlash;
1146             }
1147         }
1148 
1149 
1150         /// <devdoc>
1151         ///    <para> Gets the virtual directory of the Page or UserControl that contains this control.
1152         ///         Unlike TemplateSourceDirectory, this returns an app relative path (e.g. "~/sub")</para>
1153         /// </devdoc>
1154         [
1155         Browsable(false),
1156         EditorBrowsable(EditorBrowsableState.Advanced),
1157         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1158         WebSysDescription(SR.Control_TemplateSourceDirectory)
1159         ]
1160         public string AppRelativeTemplateSourceDirectory {
1161             get {
1162                 return VirtualPath.GetAppRelativeVirtualPathStringOrEmpty(TemplateControlVirtualDirectory);
1163             }
1164 
1165             [EditorBrowsable(EditorBrowsableState.Never)]
1166             set {
1167                 // This setter is necessary so that skins are based on hosting skin file.
1168                 this.TemplateControlVirtualDirectory = VirtualPath.CreateNonRelativeAllowNull(value);
1169             }
1170         }
1171 
1172         internal VirtualPath TemplateControlVirtualDirectory {
1173             get {
1174                 if (_occasionalFields != null && _occasionalFields.TemplateSourceVirtualDirectory != null)
1175                     return _occasionalFields.TemplateSourceVirtualDirectory;
1176 
1177                 TemplateControl control = TemplateControl;
1178                 if (control == null) {
1179                     HttpContext context = Context;
1180                     if (context != null) {
1181                         VirtualPath templateSourceVirtualDirectory = context.Request.CurrentExecutionFilePathObject.Parent;
1182                         if (templateSourceVirtualDirectory != null) {
1183                             EnsureOccasionalFields();
1184                             _occasionalFields.TemplateSourceVirtualDirectory = templateSourceVirtualDirectory;
1185                         }
1186                     }
1187                     return (_occasionalFields != null) ? _occasionalFields.TemplateSourceVirtualDirectory : null;
1188                 }
1189                 // Prevent recursion if this is the TemplateControl
1190                 if (control != this) {
1191                     VirtualPath templateSourceVirtualDirectory = control.TemplateControlVirtualDirectory;
1192                     if (templateSourceVirtualDirectory != null) {
1193                         EnsureOccasionalFields();
1194                         _occasionalFields.TemplateSourceVirtualDirectory = templateSourceVirtualDirectory;
1195                     }
1196                 }
1197                 return (_occasionalFields != null) ? _occasionalFields.TemplateSourceVirtualDirectory : null;
1198             }
1199 
1200             set {
1201                 // This setter is necessary so that skins are based on hosting skin file.
1202                 if (value != null) {
1203                     EnsureOccasionalFields();
1204                     _occasionalFields.TemplateSourceVirtualDirectory = value;
1205                 }
1206                 else {
1207                     if (_occasionalFields != null &&
1208                         _occasionalFields.TemplateSourceVirtualDirectory != null) {
1209                             _occasionalFields.TemplateSourceVirtualDirectory = null;
1210                     }
1211                 }
1212             }
1213         }
1214 
1215         internal ControlState ControlState {
1216             get { return _controlState; }
1217             set { _controlState = value; }
1218         }
1219 
1220 
1221         /// <devdoc>
1222         ///    <para>Indicates the site information for the control.</para>
1223         /// </devdoc>
1224         [
1225         Browsable(false),
1226         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1227         EditorBrowsable(EditorBrowsableState.Advanced),
1228         WebSysDescription(SR.Control_Site)
1229         ]
1230         public ISite Site {
1231             get {
1232                 if (OwnerControl != null) {
1233                     return OwnerControl.Site;
1234                 }
1235 
1236                 if (RareFields != null) {
1237                     return RareFields.Site;
1238                 }
1239                 return null;
1240             }
1241             set {
1242                 if (OwnerControl != null) {
1243                     throw new InvalidOperationException(SR.GetString(SR.Substitution_SiteNotAllowed));
1244                 }
1245 
1246                 RareFieldsEnsured.Site = value;
1247                 flags.Clear(designModeChecked);
1248             }
1249         }
1250 
1251 
1252         /// <devdoc>
1253         ///    <para>
1254         ///       Gets or sets a value that indicates whether a control should be rendered on
1255         ///       the page.
1256         ///    </para>
1257         /// </devdoc>
1258         [
1259         Bindable(true),
1260         DefaultValue(true),
1261         WebCategory("Behavior"),
1262         WebSysDescription(SR.Control_Visible)
1263         ]
1264         public virtual bool Visible {
1265             get {
1266                 if (flags[invisible])
1267                     return false;
1268                 else if ((_parent != null) && !DesignMode)
1269                     return _parent.Visible;
1270                 else
1271                     return true;
1272             }
1273             set {
1274                 if (flags[marked]) {
1275                     bool visible = !flags[invisible];
1276                     if (visible != value) {
1277                         flags.Set(visibleDirty);
1278                     }
1279                 }
1280 
1281                 if(!value) {
1282                     flags.Set(invisible);
1283                 }
1284                 else {
1285                     flags.Clear(invisible);
1286                 }
1287             }
1288         }
1289 
1290 
1291         /// <devdoc>
1292         /// Do not remove or change the signature. It is called via reflection.
1293         /// This allows for correct serialization, since Visible is implemented as a
1294         /// recursive property.
1295         /// </devdoc>
ResetVisible()1296         private void ResetVisible() {
1297             Visible = true;
1298         }
1299 
1300 
1301         /// <devdoc>
1302         /// Do not remove or change the signature. It is called via reflection.
1303         /// This allows for correct serialization, since Visible is implemented as a
1304         /// recursive property.
1305         /// </devdoc>
ShouldSerializeVisible()1306         private bool ShouldSerializeVisible() {
1307             return flags[invisible];
1308         }
1309 
1310 
1311         /// <devdoc>
1312         ///    <para> Gets the unique, hierarchically-qualified identifier for
1313         ///       a control. This is different from the ID property, in that the fully-qualified
1314         ///       identifier includes the identifier for the control's naming container.</para>
1315         /// </devdoc>
1316         [
1317         Browsable(false),
1318         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1319         WebSysDescription(SR.Control_UniqueID)
1320         ]
1321         public virtual string UniqueID {
1322             get {
1323                 if (_cachedUniqueID != null) {
1324                     return _cachedUniqueID;
1325                 }
1326 
1327                 Control namingContainer = NamingContainer;
1328                 if (namingContainer != null) {
1329                     // if the ID is null at this point, we need to have one created and the control added to the
1330                     // naming container.
1331                     if (_id == null) {
1332                         GenerateAutomaticID();
1333                     }
1334 
1335                     if (Page == namingContainer) {
1336                         _cachedUniqueID = _id;
1337                     }
1338                     else {
1339                         string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();
1340                         if (uniqueIDPrefix.Length == 0) {
1341                             // In this case, it is probably a naming container that is not sited, so we don't want to cache it
1342                             return _id;
1343                         }
1344                         else {
1345                             _cachedUniqueID = uniqueIDPrefix + _id;
1346                         }
1347                     }
1348 
1349                     return _cachedUniqueID;
1350                 }
1351                 else {
1352                     // no naming container
1353                     return _id;
1354                 }
1355             }
1356         }
1357 
1358         [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID", Justification="This is consistent with UniqueID")]
1359         [SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "Member", Justification="This is consistent with UniqueID")]
GetUniqueIDRelativeTo(Control control)1360         public string GetUniqueIDRelativeTo(Control control) {
1361             if (control == null) {
1362                 throw new ArgumentNullException("control");
1363             }
1364 
1365             if (!IsDescendentOf(control.NamingContainer)) {
1366                 throw new InvalidOperationException(SR.GetString(SR.Control_NotADescendentOfNamingContainer, control.ID));
1367             }
1368 
1369             if (control.NamingContainer == Page) {
1370                 return UniqueID;
1371             } else {
1372                 return UniqueID.Substring(control.NamingContainer.UniqueID.Length + 1); // add 1 for the ID seperator (which is a char)
1373             }
1374         }
1375 
1376         /// <devdoc>
1377         ///    <para>Occurs when the control binds to a data source. Notifies the control to perform any data binding during this event.</para>
1378         /// </devdoc>
1379         [
1380         WebCategory("Data"),
1381         WebSysDescription(SR.Control_OnDataBind)
1382         ]
1383         public event EventHandler DataBinding {
1384             add {
1385                 Events.AddHandler(EventDataBinding, value);
1386             }
1387             remove {
1388                 Events.RemoveHandler(EventDataBinding, value);
1389             }
1390         }
1391 
1392 
1393         /// <devdoc>
1394         ///    <para>Occurs when the control is initialized, the first step in the page lifecycle. Controls should
1395         ///       perform any initialization steps that are required to create and set up an
1396         ///       instantiation.</para>
1397         /// </devdoc>
1398         [
1399         WebSysDescription(SR.Control_OnInit)
1400         ]
1401         public event EventHandler Init {
1402             add {
1403                 Events.AddHandler(EventInit, value);
1404             }
1405             remove {
1406                 Events.RemoveHandler(EventInit, value);
1407             }
1408         }
1409 
1410 
1411         /// <devdoc>
1412         /// <para>Occurs when the control is loaded to the <see cref='System.Web.UI.Page'/> object. Notifies the control to perform any steps that
1413         ///    need to occur on each page request.</para>
1414         /// </devdoc>
1415         [
1416         WebSysDescription(SR.Control_OnLoad)
1417         ]
1418         public event EventHandler Load {
1419             add {
1420                 Events.AddHandler(EventLoad, value);
1421             }
1422             remove {
1423                 Events.RemoveHandler(EventLoad, value);
1424             }
1425         }
1426 
1427 
1428         /// <devdoc>
1429         ///    <para>Occurs when the control is about to render. Controls
1430         ///       should perform any pre-rendering steps necessary before saving view state and
1431         ///       rendering content to the <see cref='System.Web.UI.Page'/> object.</para>
1432         /// </devdoc>
1433         [
1434         WebSysDescription(SR.Control_OnPreRender)
1435         ]
1436         public event EventHandler PreRender {
1437             add {
1438                 Events.AddHandler(EventPreRender, value);
1439             }
1440             remove {
1441                 Events.RemoveHandler(EventPreRender, value);
1442             }
1443         }
1444 
1445 
1446         /// <devdoc>
1447         ///    <para>Occurs when the control is unloaded from memory. Controls should perform any
1448         ///       final cleanup before this instance of it is </para>
1449         /// </devdoc>
1450         [
1451         WebSysDescription(SR.Control_OnUnload)
1452         ]
1453         public event EventHandler Unload {
1454             add {
1455                 Events.AddHandler(EventUnload, value);
1456             }
1457             remove {
1458                 Events.RemoveHandler(EventUnload, value);
1459             }
1460         }
1461 
1462         /// <devdoc>
1463         /// <para>Apply stylesheet skin on the control.</para>
1464         /// </devdoc>
1465         [
1466         EditorBrowsable(EditorBrowsableState.Advanced),
1467         ]
ApplyStyleSheetSkin(Page page)1468         public virtual void ApplyStyleSheetSkin(Page page) {
1469             // Nothing to do if the control is not in a Page.
1470             if (page == null) {
1471                 return;
1472             }
1473 
1474             // Only apply stylesheet if not already applied.
1475             if (flags[styleSheetApplied]) {
1476                 throw new InvalidOperationException(SR.GetString(SR.StyleSheetAreadyAppliedOnControl));
1477             }
1478 
1479             if (page.ApplyControlStyleSheet(this)) {
1480                 flags.Set(styleSheetApplied);
1481             }
1482         }
1483 
1484         /// <devdoc>
1485         /// <para>Apply theme on the control.</para>
1486         /// </devdoc>
ApplySkin(Page page)1487         private void ApplySkin(Page page) {
1488             if (page == null) {
1489                 throw new ArgumentNullException("page");
1490             }
1491 
1492             if (flags[themeApplied]) {
1493                 return;
1494             }
1495 
1496             if (ThemeableAttribute.IsTypeThemeable(this.GetType())) {
1497                 page.ApplyControlSkin(this);
1498                 flags.Set(themeApplied);
1499             }
1500         }
1501 
1502 
1503         /// <devdoc>
1504         /// <para>Raises the <see langword='DataBinding'/> event. This
1505         ///    notifies a control to perform any data binding logic that is associated with it.</para>
1506         /// </devdoc>
OnDataBinding(EventArgs e)1507         protected virtual void OnDataBinding(EventArgs e) {
1508             if(HasEvents()) {
1509                 EventHandler handler = _events[EventDataBinding] as EventHandler;
1510                 if(handler != null) {
1511                     handler(this, e);
1512                 }
1513             }
1514         }
1515 
1516 
1517         /// <devdoc>
1518         ///    <para> Causes data binding to occur on the invoked control and all of its child
1519         ///       controls.</para>
1520         /// </devdoc>
DataBind()1521         public virtual void DataBind() {
1522             DataBind(true);
1523         }
1524 
1525         /// <devdoc>
1526         ///    <para> Causes the invoked controls' context to be pushed on the stack,
1527         ///       then conditionally call OnDataBinging on the invoked control, and databind all of its child
1528         ///       controls.  A control would call this with false if it overrides DataBind without calling
1529         ///       Control.DataBind, but still wants to be an IDataItemContainer.  FormView and DetailsView
1530         ///       are good examples of this.</para>
1531         /// </devdoc>
DataBind(bool raiseOnDataBinding)1532         protected virtual void DataBind(bool raiseOnDataBinding) {
1533             bool inDataBind = false;
1534 
1535             if (IsBindingContainer) {
1536                 bool foundDataItem;
1537 
1538                 object dataItem = DataBinder.GetDataItem(this, out foundDataItem);
1539 
1540                 if (foundDataItem && (Page != null)) {
1541                     Page.PushDataBindingContext(dataItem);
1542                     inDataBind = true;
1543                 }
1544             }
1545             try {
1546                 if (raiseOnDataBinding) {
1547                     // Do our own databinding
1548                     OnDataBinding(EventArgs.Empty);
1549                 }
1550 
1551                 // Do all of our children's databinding
1552                 DataBindChildren();
1553             }
1554             finally {
1555                 if (inDataBind) {
1556                     Page.PopDataBindingContext();
1557                 }
1558             }
1559         }
1560 
1561 
1562         /// <devdoc>
1563         /// <para> Causes data binding to occur on all of the child controls.</para>
1564         /// </devdoc>
DataBindChildren()1565         protected virtual void DataBindChildren() {
1566             if (HasControls()) {
1567                 string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
1568 
1569                 try {
1570                     try {
1571                         int controlCount = _controls.Count;
1572                         for (int i=0; i < controlCount; i++)
1573                             _controls[i].DataBind();
1574                     }
1575                     finally {
1576                         _controls.SetCollectionReadOnly(oldmsg);
1577                     }
1578                 }
1579                 catch {
1580                     throw;
1581                 }
1582             }
1583         }
1584 
PreventAutoID()1585         internal void PreventAutoID() {
1586             // controls that are also naming containers must always get an id
1587             if (flags[isNamingContainer] == false) {
1588                 flags.Set(idNotRequired);
1589             }
1590         }
1591 
1592 
1593         /// <devdoc>
1594         ///    <para>Notifies the control that an element, XML or HTML, was parsed, and adds it to
1595         ///       the control.</para>
1596         /// </devdoc>
AddParsedSubObject(object obj)1597         protected virtual void AddParsedSubObject(object obj) {
1598             Control control = obj as Control;
1599             if (control != null) {
1600                 Controls.Add(control);
1601             }
1602         }
1603 
UpdateNamingContainer(Control namingContainer)1604         private void UpdateNamingContainer(Control namingContainer) {
1605             // Remove the cached uniqueID if the control already had a namingcontainer
1606             // and the namingcontainer is changed.
1607             if (_namingContainer == null || (_namingContainer != null && _namingContainer != namingContainer)) {
1608                 ClearCachedUniqueIDRecursive();
1609             }
1610 
1611             // No need to clear the cache if never been initialized
1612             if (EffectiveClientIDModeValue != ClientIDMode.Inherit) {
1613                 ClearCachedClientID();
1614                 ClearEffectiveClientIDMode();
1615             }
1616 
1617             _namingContainer = namingContainer;
1618         }
1619 
ClearCachedUniqueIDRecursive()1620         private void ClearCachedUniqueIDRecursive() {
1621             _cachedUniqueID = null;
1622 
1623             if (_occasionalFields != null) {
1624                 _occasionalFields.UniqueIDPrefix = null;
1625             }
1626 
1627             if (_controls != null) {
1628                 int controlCount = _controls.Count;
1629                 for (int i = 0; i < controlCount; i++) {
1630                     _controls[i].ClearCachedUniqueIDRecursive();
1631                 }
1632             }
1633         }
1634 
EnsureID()1635         protected void EnsureID() {
1636             if (_namingContainer != null) {
1637                 if (_id == null) {
1638                     GenerateAutomaticID();
1639                 }
1640                 flags.Set(mustRenderID);
1641             }
1642         }
1643 
GenerateAutomaticID()1644         private void GenerateAutomaticID() {
1645             Debug.Assert(_namingContainer != null);
1646             Debug.Assert(_id == null);
1647 
1648             // Remember that a generated ID is used for this control.
1649             flags.Set(useGeneratedID);
1650 
1651             // Calculate the automatic ID. For performance and memory reasons
1652             // we look up a static table entry if possible
1653             _namingContainer.EnsureOccasionalFields();
1654             int idNo = _namingContainer._occasionalFields.NamedControlsID++;
1655             if (EnableLegacyRendering) {
1656                 // VSWhidbey 517118
1657                 _id = automaticLegacyIDPrefix + idNo.ToString(NumberFormatInfo.InvariantInfo);
1658             }
1659             else {
1660                 if (idNo < automaticIDCount) {
1661                     _id = automaticIDs[idNo];
1662                 }
1663                 else {
1664                     _id = automaticIDPrefix + idNo.ToString(NumberFormatInfo.InvariantInfo);
1665                 }
1666             }
1667 
1668             _namingContainer.DirtyNameTable();
1669         }
1670 
GetUniqueIDPrefix()1671         internal virtual string GetUniqueIDPrefix() {
1672             EnsureOccasionalFields();
1673 
1674             if (_occasionalFields.UniqueIDPrefix == null) {
1675                 string uniqueID = UniqueID;
1676                 if (!String.IsNullOrEmpty(uniqueID)) {
1677                     _occasionalFields.UniqueIDPrefix = uniqueID + IdSeparator;
1678                 }
1679                 else {
1680                     _occasionalFields.UniqueIDPrefix = String.Empty;
1681                 }
1682             }
1683 
1684             return _occasionalFields.UniqueIDPrefix;
1685         }
1686 
1687         /// <devdoc>
1688         /// <para>Raises the <see langword='Init'/> event. This notifies the control to perform
1689         ///    any steps necessary for its creation on a page request.</para>
1690         /// </devdoc>
OnInit(EventArgs e)1691         protected internal virtual void OnInit(EventArgs e) {
1692             if(HasEvents()) {
1693                 EventHandler handler = _events[EventInit] as EventHandler;
1694                 if(handler != null) {
1695                     handler(this, e);
1696                 }
1697             }
1698         }
1699 
1700         // !! IMPORTANT !!
1701         // If you make changes to this method, also change InitRecursiveAsync.
InitRecursive(Control namingContainer)1702         internal virtual void InitRecursive(Control namingContainer) {
1703             ResolveAdapter();
1704             if (_controls != null) {
1705                 if (flags[isNamingContainer]) {
1706                     namingContainer = this;
1707                 }
1708                 string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
1709 
1710                 int controlCount = _controls.Count;
1711                 for (int i = 0; i < controlCount; i++) {
1712                     Control control = _controls[i];
1713 
1714                     // Propagate the page and namingContainer
1715                     control.UpdateNamingContainer(namingContainer);
1716 
1717                     if ((control._id == null) && (namingContainer != null) && !control.flags[idNotRequired]) {
1718                         control.GenerateAutomaticID();
1719                     }
1720                     control._page = Page;
1721 
1722                     control.InitRecursive(namingContainer);
1723                 }
1724                 _controls.SetCollectionReadOnly(oldmsg);
1725 
1726             }
1727 
1728             // Only make the actual call if it hasn't already happened (ASURT 111303)
1729             if (_controlState < ControlState.Initialized) {
1730                 _controlState = ControlState.ChildrenInitialized; // framework also initialized
1731 
1732                 if ((Page != null) && !DesignMode) {
1733                     if (Page.ContainsTheme && EnableTheming) {
1734                         ApplySkin(Page);
1735                     }
1736                 }
1737 
1738                 if (AdapterInternal != null) {
1739                     AdapterInternal.OnInit(EventArgs.Empty);
1740                 }
1741                 else {
1742                     OnInit(EventArgs.Empty);
1743                 }
1744 
1745                 _controlState = ControlState.Initialized;
1746             }
1747 
1748             // track all subsequent state changes
1749             TrackViewState();
1750 
1751 #if DEBUG
1752             ControlInvariant();
1753 #endif
1754         }
1755 
1756         // TAP version of InitRecursive
1757         // !! IMPORTANT !!
1758         // If you make changes to this method, also change InitRecursive.
InitRecursiveAsync(Control namingContainer, Page page)1759         internal async Task InitRecursiveAsync(Control namingContainer, Page page) {
1760             ResolveAdapter();
1761             if (_controls != null) {
1762                 if (flags[isNamingContainer]) {
1763                     namingContainer = this;
1764                 }
1765                 string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
1766 
1767                 int controlCount = _controls.Count;
1768                 for (int i = 0; i < controlCount; i++) {
1769                     Control control = _controls[i];
1770 
1771                     // Propagate the page and namingContainer
1772                     control.UpdateNamingContainer(namingContainer);
1773 
1774                     if ((control._id == null) && (namingContainer != null) && !control.flags[idNotRequired]) {
1775                         control.GenerateAutomaticID();
1776                     }
1777                     control._page = Page;
1778 
1779                     control.InitRecursive(namingContainer);
1780                 }
1781                 _controls.SetCollectionReadOnly(oldmsg);
1782 
1783             }
1784 
1785             // Only make the actual call if it hasn't already happened (ASURT 111303)
1786             if (_controlState < ControlState.Initialized) {
1787                 _controlState = ControlState.ChildrenInitialized; // framework also initialized
1788 
1789                 if ((Page != null) && !DesignMode) {
1790                     if (Page.ContainsTheme && EnableTheming) {
1791                         ApplySkin(Page);
1792                     }
1793                 }
1794 
1795                 using (page.Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
1796                     if (AdapterInternal != null) {
1797                         AdapterInternal.OnInit(EventArgs.Empty);
1798                     }
1799                     else {
1800                         OnInit(EventArgs.Empty);
1801                     }
1802                     await page.GetWaitForPreviousStepCompletionAwaitable();
1803                 }
1804 
1805                 _controlState = ControlState.Initialized;
1806             }
1807 
1808             // track all subsequent state changes
1809             TrackViewState();
1810 
1811 #if DEBUG
1812             ControlInvariant();
1813 #endif
1814         }
1815 
1816 #if DEBUG
1817 
1818         /// <devdoc>
1819         ///    <para>This should be used to assert internal state about the control</para>
1820         /// </devdoc>
ControlInvariant()1821         internal void ControlInvariant() {
1822 
1823             // If the control is initialized, the naming container and page should have been pushed in
1824             if (_controlState >= ControlState.Initialized) {
1825                 if (DesignMode) {
1826                     // Top-level UserControls do not have a page or a naming container in the designer
1827                     // hence the special casing.
1828 
1829                     Debug.Assert((_namingContainer != null) || (this is Page) || (this is UserControl));
1830 
1831                     //
1832 
1833 
1834 
1835                 }
1836                 else {
1837                     if (!(this is Page)) {
1838                         Debug.Assert(_namingContainer != null);
1839                     }
1840                     Debug.Assert(Page != null);
1841                 }
1842             }
1843             // If naming container is set and the name table exists, the ID should exist in it.
1844 
1845             if(_namingContainer != null &&
1846                _namingContainer._occasionalFields != null &&
1847                _namingContainer._occasionalFields.NamedControls != null &&
1848                _id != null) {
1849                 Debug.Assert(_namingContainer._occasionalFields.NamedControls.Contains(_id));
1850             }
1851         }
1852 
1853         // Collect some statistic about the number of controls with occasional and
1854         // rare fields.
GetRareFieldStatistics(ref int totalControls, ref int withOccasionalFields, ref int withRareFields)1855         internal void GetRareFieldStatistics(ref int totalControls,
1856             ref int withOccasionalFields, ref int withRareFields) {
1857             totalControls++;
1858             if (_occasionalFields != null) {
1859                 withOccasionalFields++;
1860                 if (_occasionalFields.RareFields != null)
1861                     withRareFields++;
1862 
1863                 // No children: we're done
1864                 if (_controls == null)
1865                     return;
1866 
1867                 int controlCount = _controls.Count;
1868                 for (int i = 0; i < controlCount; i++) {
1869                     Control control = _controls[i];
1870 
1871                     control.GetRareFieldStatistics(ref totalControls, ref withOccasionalFields,
1872                         ref withRareFields);
1873                 }
1874             }
1875         }
1876 #endif
1877 
ClearChildState()1878         protected void ClearChildState() {
1879             ClearChildControlState();
1880             ClearChildViewState();
1881         }
1882 
ClearChildControlState()1883         protected void ClearChildControlState() {
1884             //VSWhidbey 242621 to be consistent with ClearChildViewState, ignore calls before and during Init
1885             if (ControlState < ControlState.Initialized) {
1886                 return;
1887             }
1888             flags.Set(disableChildControlState);
1889             if (Page != null) {
1890                 Page.RegisterRequiresClearChildControlState(this);
1891             }
1892         }
1893 
1894 
1895         /// <devdoc>
1896         ///    <para>Deletes the view state information for all of the current control's child
1897         ///       controls.</para>
1898         /// </devdoc>
ClearChildViewState()1899         protected void ClearChildViewState() {
1900             if(_occasionalFields != null) {
1901                 _occasionalFields.ControlsViewState = null;
1902             }
1903         }
1904 
1905         [SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId="Member")]
ClearEffectiveClientIDMode()1906         protected void ClearEffectiveClientIDMode() {
1907             EffectiveClientIDModeValue = ClientIDMode.Inherit;
1908             if (HasControls()) {
1909                 foreach (Control control in Controls) {
1910                     control.ClearEffectiveClientIDMode();
1911                 }
1912             }
1913         }
1914 
1915         [SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId="Member")]
ClearCachedClientID()1916         protected void ClearCachedClientID() {
1917             _cachedPredictableID = null;
1918             if (HasControls()) {
1919                 foreach (Control control in Controls) {
1920                     control.ClearCachedClientID();
1921                 }
1922             }
1923         }
1924 
1925         /// <devdoc>
1926         ///    <para>Indicates whether the current control's children have any saved view state
1927         ///       information. This property is read-only.</para>
1928         /// </devdoc>
1929         protected bool HasChildViewState {
1930             get {
1931                 return ((_occasionalFields != null) &&
1932                         (_occasionalFields.ControlsViewState != null) &&
1933                         (_occasionalFields.ControlsViewState.Count > 0));
1934             }
1935         }
1936 
1937 
1938         /// <devdoc>
1939         /// Sets initial focus on the control
1940         /// </devdoc>
Focus()1941         public virtual void Focus() {
1942             Page.SetFocus(this);
1943         }
1944 
LoadControlStateInternal(object savedStateObj)1945         internal void LoadControlStateInternal(object savedStateObj) {
1946             // Do not load the control state if it has been applied.
1947             if (flags[controlStateApplied]) {
1948                 return;
1949             }
1950 
1951             flags.Set(controlStateApplied);
1952 
1953             Pair savedState = (Pair)savedStateObj;
1954             if (savedState == null) {
1955                 return;
1956             }
1957             Page page = Page;
1958             if (page != null && !page.ShouldLoadControlState(this)) {
1959                 return;
1960             }
1961             // VSWhidbey160650: Only call LoadControlState with non null savedState
1962             if (savedState.First != null) {
1963                 LoadControlState(savedState.First);
1964             }
1965             // VSWhidbey356804: Only call LoadAdapterControlState with non null savedState
1966             if (AdapterInternal == null || savedState.Second == null) {
1967                 return;
1968             }
1969             AdapterInternal.LoadAdapterControlState(savedState.Second);
1970         }
1971 
1972 
1973         /// <devdoc>
1974         /// Load the control state, which is the essential state information needed even if view state is disabled.
1975         /// </devdoc>
LoadControlState(object savedState)1976         protected internal virtual void LoadControlState(object savedState) {
1977         }
1978 
1979 
1980         /// <devdoc>
1981         ///    <para>Restores the view state information from a previous page
1982         ///       request that was saved by the Control.SavedState method.</para>
1983         /// </devdoc>
LoadViewState(object savedState)1984         protected virtual void LoadViewState(object savedState) {
1985             if (savedState != null) {
1986                 ViewState.LoadViewState(savedState);
1987 
1988                 // Load values cached out of view state
1989                 object visible = ViewState["Visible"];
1990                 if (visible != null) {
1991                     if(!(bool)visible) {
1992                         flags.Set(invisible);
1993                     }
1994                     else {
1995                         flags.Clear(invisible);
1996                     }
1997                     flags.Set(visibleDirty);
1998                 }
1999 
2000                 object validateRequestModeValue = ViewState["ValidateRequestMode"];
2001                 if (validateRequestModeValue != null) {
2002                     flags[validateRequestMode, validateRequestModeOffset] = (int)validateRequestModeValue;
2003                     flags.Set(validateRequestModeDirty);
2004                 }
2005             }
2006         }
2007 
LoadViewStateRecursive(object savedState)2008         internal void LoadViewStateRecursive(object savedState) {
2009             // nothing to do if we have no state
2010             if (savedState == null || flags[disableViewState])
2011                 return;
2012 
2013             if (Page != null && Page.IsPostBack) {
2014                 object controlState = null;
2015                 object adapterState = null;
2016                 ArrayList childState = null;
2017 
2018                 Pair allSavedState = savedState as Pair;
2019                 if (allSavedState != null) {
2020                     controlState = allSavedState.First;
2021                     childState = (ArrayList)allSavedState.Second;
2022                 }
2023                 else {
2024                     Debug.Assert(savedState is Triplet);
2025                     Triplet t = (Triplet)savedState;
2026 
2027                     controlState = t.First;
2028                     adapterState = t.Second;
2029                     childState = (ArrayList)t.Third;
2030                 }
2031 
2032                 try {
2033                     if ((adapterState != null) && (AdapterInternal != null)) {
2034                         AdapterInternal.LoadAdapterViewState(adapterState);
2035                     }
2036 
2037                     if (controlState != null) {
2038                         LoadViewState(controlState);
2039                     }
2040 
2041                     if (childState != null) {
2042                         if (LoadViewStateByID) {
2043                             LoadChildViewStateByID(childState);
2044                         }
2045                         else {
2046                             LoadChildViewStateByIndex(childState);
2047                         }
2048                     }
2049                 }
2050                 catch (InvalidCastException) {
2051                     // catch all viewstate loading problems with casts.  They are most likely changed control trees.
2052                     throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
2053                 }
2054                 catch (IndexOutOfRangeException) {
2055                     // catch all viewstate loading problems with indeces.  They are most likely changed control trees.
2056                     throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
2057                 }
2058             }
2059 
2060             _controlState = ControlState.ViewStateLoaded;
2061         }
2062 
LoadChildViewStateByID(ArrayList childState)2063         internal void LoadChildViewStateByID(ArrayList childState) {
2064             int childStateCount = childState.Count;
2065             for (int i = 0; i < childStateCount; i += 2) {
2066                 // first element is index or ID of control with state and the
2067                 // next element is state of the control
2068                 string controlId = (string)childState[i];
2069                 object state = childState[i + 1];
2070 
2071                 Control childControl = FindControl(controlId);
2072                 if (childControl != null) {
2073                     childControl.LoadViewStateRecursive(state);
2074                 }
2075                 else {
2076                     // couldn't find a control for this state blob, save it for later
2077                     EnsureOccasionalFields();
2078                     if (_occasionalFields.ControlsViewState == null) {
2079                         _occasionalFields.ControlsViewState = new Hashtable();
2080                     }
2081                     _occasionalFields.ControlsViewState[controlId] = state;
2082                 }
2083             }
2084         }
2085 
LoadChildViewStateByIndex(ArrayList childState)2086         internal void LoadChildViewStateByIndex(ArrayList childState) {
2087             ControlCollection ctrlColl = Controls;
2088             int ctrlCount = ctrlColl.Count;
2089 
2090             int childStateCount = childState.Count;
2091             for (int i = 0; i < childStateCount; i += 2) {
2092                 // first element is index of control with state and the
2093                 // next element is state of the control
2094                 int controlIndex = (int)childState[i];
2095                 object state = childState[i + 1];
2096 
2097                 if (controlIndex < ctrlCount) {
2098                     // we have a control for this state blob
2099                     ctrlColl[controlIndex].LoadViewStateRecursive(state);
2100                 }
2101                 else {
2102                     // couldn't find a control for this state blob, save it for later
2103                     EnsureOccasionalFields();
2104                     if (_occasionalFields.ControlsViewState == null) {
2105                         _occasionalFields.ControlsViewState = new Hashtable();
2106                     }
2107                     _occasionalFields.ControlsViewState[controlIndex] = state;
2108                 }
2109             }
2110         }
2111 
2112         ///
2113         /// Figure out if a path is physical or virtual.  This is useful because a number of our controls
2114         /// accept either type of path for the same attribute.
2115         ///
ResolvePhysicalOrVirtualPath(string path, out VirtualPath virtualPath, out string physicalPath)2116         internal void ResolvePhysicalOrVirtualPath(string path, out VirtualPath virtualPath, out string physicalPath) {
2117             if (System.Web.Util.UrlPath.IsAbsolutePhysicalPath(path)) {
2118                 physicalPath = path;
2119                 virtualPath = null;
2120             }
2121             else {
2122                 physicalPath = null;
2123 
2124                 // It could be relative, so resolve it
2125                 virtualPath = TemplateControlVirtualDirectory.Combine(VirtualPath.Create(path));
2126             }
2127         }
2128 
2129 
2130         /// <devdoc>
2131         /// <para>
2132         ///   This function takes a virtual path, that is a relative or root relative URL without a protocol.
2133         ///   It returns the mapped physcial file name relative to the template source. It throws an exception if
2134         ///   there is insufficient security access to read or investigate the mapped result. This should be used
2135         ///   by controls that can read files and live in fully trusted DLLs such as System.Web.dll to prevent
2136         ///   security issues. The exception thrown does not give away information about the mapping.  For absolute
2137         ///   physical paths, this function checks permission
2138         /// </para>
2139         /// </devdoc>
MapPathSecure(string virtualPath)2140         protected internal string MapPathSecure(string virtualPath) {
2141             if (String.IsNullOrEmpty(virtualPath)) {
2142                 throw new ArgumentNullException("virtualPath", SR.GetString(SR.VirtualPath_Length_Zero));
2143             }
2144 
2145             string physicalPath;
2146             VirtualPath virtualPathObject;
2147             ResolvePhysicalOrVirtualPath(virtualPath, out virtualPathObject, out physicalPath);
2148             if (physicalPath == null) {
2149                 physicalPath = virtualPathObject.MapPathInternal(TemplateControlVirtualDirectory,
2150                     true /*allowCrossAppMapping*/);
2151             }
2152 
2153             // Security check
2154             HttpRuntime.CheckFilePermission(physicalPath);
2155 
2156             return physicalPath;
2157         }
2158 
2159 
2160         /// <devdoc>
2161         /// <para>
2162         ///   This function takes a virtual path, that is a relative or root relative URL without a protocol.
2163         ///   It can also take a physical path, either local (c:\) or UNC.
2164         ///   It returns a stream used to read to contents of the file. It throws an exception if
2165         ///   there is insufficient security access to read or investigate the mapped result. This should be used
2166         ///   by controls that can read files and live in fully trusted DLLs such as System.Web.dll to prevent
2167         ///   security issues. The exception thrown does not give away information about the mapping.  For absolute
2168         ///   physical paths, this function checks permission
2169         /// </para>
2170         /// </devdoc>
OpenFile(string path)2171         protected internal Stream OpenFile(string path) {
2172 
2173             string physicalPath = null;
2174             VirtualFile vfile = null;
2175 
2176             // Need to Trim it since MapPath no longer allows trailing space (VSWhidbey 441210)
2177             path = path.Trim();
2178 
2179             if (UrlPath.IsAbsolutePhysicalPath(path)) {
2180                 // Absolute physical path
2181                 physicalPath = path;
2182             }
2183             else {
2184                 vfile = HostingEnvironment.VirtualPathProvider.GetFile(path);
2185                 MapPathBasedVirtualFile mapPathVFile = vfile as MapPathBasedVirtualFile;
2186                 if (mapPathVFile != null) {
2187                     physicalPath = mapPathVFile.PhysicalPath;
2188                 }
2189             }
2190 
2191             // If we got a physical path, make sure the user has access to it
2192             if (physicalPath != null) {
2193                 HttpRuntime.CheckFilePermission(physicalPath);
2194             }
2195 
2196             if (vfile != null) {
2197                 return vfile.Open();
2198             }
2199             else {
2200                 return new FileStream(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
2201             }
2202         }
2203 
2204         ///
2205         /// Open a stream from either a virtual or physical path, and if possible get a CacheDependency
2206         /// for the resulting Stream.
2207         ///
OpenFileAndGetDependency(VirtualPath virtualPath, string physicalPath, out CacheDependency dependency)2208         internal Stream OpenFileAndGetDependency(VirtualPath virtualPath, string physicalPath, out CacheDependency dependency) {
2209 
2210             // Only one of the paths should be non-null
2211             Debug.Assert((virtualPath == null) != (physicalPath == null));
2212 
2213             // If we got a virtual path, and we're using the default VPP, call MapPath
2214             if (physicalPath == null && HostingEnvironment.UsingMapPathBasedVirtualPathProvider) {
2215                 physicalPath = virtualPath.MapPathInternal(TemplateControlVirtualDirectory,
2216                     true /*allowCrossAppMapping*/);
2217             }
2218 
2219             Stream stream;
2220             if (physicalPath != null) {
2221                 // Security check
2222                 HttpRuntime.CheckFilePermission(physicalPath);
2223 
2224                 // Work directly with the physical file, bypassing the VPP
2225                 stream = new FileStream(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
2226                 dependency = new CacheDependency(0, physicalPath);
2227             }
2228             else {
2229                 // It's non file system based, so go though the VirtualPathProvider
2230                 stream = virtualPath.OpenFile();
2231                 dependency = VirtualPathProvider.GetCacheDependency(virtualPath);
2232             }
2233 
2234             return stream;
2235         }
2236 
2237 
2238         /// <devdoc>
2239         /// <para>Raises the <see langword='Load'/>
2240         /// event. This notifies the control that it should perform any work that needs to
2241         /// occur for each page request.</para>
2242         /// </devdoc>
OnLoad(EventArgs e)2243         protected internal virtual void OnLoad(EventArgs e) {
2244             if(HasEvents()) {
2245                 EventHandler handler = _events[EventLoad] as EventHandler;
2246                 if(handler != null) {
2247                     handler(this, e);
2248                 }
2249             }
2250         }
2251 
LoadRecursive()2252         internal virtual void LoadRecursive() {
2253             // Only make the actual call if it hasn't already happened (ASURT 111303)
2254             if (_controlState < ControlState.Loaded) {
2255                 if (AdapterInternal != null) {
2256                     AdapterInternal.OnLoad(EventArgs.Empty);
2257                 }
2258                 else {
2259                     OnLoad(EventArgs.Empty);
2260                 }
2261             }
2262 
2263             // Call Load on all our children
2264             if (_controls != null) {
2265                 string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
2266 
2267                 int controlCount = _controls.Count;
2268                 for (int i = 0; i < controlCount; i++) {
2269                     _controls[i].LoadRecursive();
2270                 }
2271 
2272                 _controls.SetCollectionReadOnly(oldmsg);
2273             }
2274 
2275             if (_controlState < ControlState.Loaded)
2276                 _controlState = ControlState.Loaded;
2277         }
2278 
2279         // Same as LoadRecursive, but has an async point immediately after the call to this.OnLoad.
LoadRecursiveAsync(Page page)2280         internal async Task LoadRecursiveAsync(Page page) {
2281             // Only make the actual call if it hasn't already happened (ASURT 111303)
2282             if (_controlState < ControlState.Loaded) {
2283                 using (page.Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
2284                     if (AdapterInternal != null) {
2285                         AdapterInternal.OnLoad(EventArgs.Empty);
2286                     }
2287                     else {
2288                         OnLoad(EventArgs.Empty);
2289                     }
2290                     await page.GetWaitForPreviousStepCompletionAwaitable();
2291                 }
2292             }
2293 
2294             // Call Load on all our children
2295             if (_controls != null) {
2296                 string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
2297 
2298                 int controlCount = _controls.Count;
2299                 for (int i = 0; i < controlCount; i++) {
2300                     _controls[i].LoadRecursive();
2301                 }
2302 
2303                 _controls.SetCollectionReadOnly(oldmsg);
2304             }
2305 
2306             if (_controlState < ControlState.Loaded)
2307                 _controlState = ControlState.Loaded;
2308         }
2309 
2310         /// <devdoc>
2311         /// <para>Raises the <see langword='PreRender'/> event. This method uses event arguments
2312         ///    to pass the event data to the control.</para>
2313         /// </devdoc>
OnPreRender(EventArgs e)2314         protected internal virtual void OnPreRender(EventArgs e) {
2315             if(HasEvents()) {
2316                 EventHandler handler = _events[EventPreRender] as EventHandler;
2317                 if (handler != null) {
2318                     handler(this, e);
2319                 }
2320             }
2321         }
2322 
PreRenderRecursiveInternal()2323         internal virtual void PreRenderRecursiveInternal() {
2324             // Call Visible property and cache value in !flags[invisible] to allow Visible to be overridden.
2325             // This avoids unnecessary virtual property calls in SaveViewState and Render.
2326             bool visible = Visible;
2327             if(!visible) {
2328                 flags.Set(invisible);
2329             }
2330             else {
2331                 flags.Clear(invisible);
2332                 EnsureChildControls();
2333 
2334                 if (AdapterInternal != null) {
2335                     AdapterInternal.OnPreRender(EventArgs.Empty);
2336                 }
2337                 else {
2338                     OnPreRender(EventArgs.Empty);
2339                 }
2340 
2341                 if (_controls != null) {
2342                     string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
2343 
2344                     int controlCount = _controls.Count;
2345                     for (int i=0; i < controlCount; i++) {
2346                         _controls[i].PreRenderRecursiveInternal();
2347                     }
2348                     _controls.SetCollectionReadOnly(oldmsg);
2349                 }
2350             }
2351             _controlState = ControlState.PreRendered;
2352         }
2353 
2354         // Same as PreRenderRecursive, but has an async point after the call to this.OnPreRender.
PreRenderRecursiveInternalAsync(Page page)2355         internal async Task PreRenderRecursiveInternalAsync(Page page) {
2356             // Call Visible property and cache value in !flags[invisible] to allow Visible to be overridden.
2357             // This avoids unnecessary virtual property calls in SaveViewState and Render.
2358             bool visible = Visible;
2359             if (!visible) {
2360                 flags.Set(invisible);
2361             }
2362             else {
2363                 flags.Clear(invisible);
2364                 if (AppSettings.EnableAsyncModelBinding) {
2365                     using (page.Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
2366                         EnsureChildControls();
2367                         await page.GetWaitForPreviousStepCompletionAwaitable();
2368                     }
2369                 }
2370                 else {
2371                     EnsureChildControls();
2372                 }
2373 
2374                 using (page.Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
2375                     if (AdapterInternal != null) {
2376                         AdapterInternal.OnPreRender(EventArgs.Empty);
2377                     }
2378                     else {
2379                         OnPreRender(EventArgs.Empty);
2380                     }
2381                     await page.GetWaitForPreviousStepCompletionAwaitable();
2382                 }
2383 
2384                 if (_controls != null) {
2385                     string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
2386 
2387                     int controlCount = _controls.Count;
2388                     for (int i = 0; i < controlCount; i++) {
2389                         if (AppSettings.EnableAsyncModelBinding) {
2390                             // To make sure every OnPreRender is awaited so that _controlState
2391                             // would not be set to ControlState.PreRendered until the control is
2392                             // really PreRendered
2393                             await _controls[i].PreRenderRecursiveInternalAsync(page);
2394                         }
2395                         else {
2396                             _controls[i].PreRenderRecursiveInternal();
2397                         }
2398                     }
2399 
2400                     _controls.SetCollectionReadOnly(oldmsg);
2401                 }
2402             }
2403             _controlState = ControlState.PreRendered;
2404         }
2405 
EstimateStateSize(object state)2406         internal int EstimateStateSize(object state) {
2407             if(state == null) {
2408                 return 0;
2409             }
2410             return Util.SerializeWithAssert(new ObjectStateFormatter(), state).Length;
2411         }
2412 
2413         /*
2414          * Walk the tree and fill in profile information
2415          */
2416 
2417         /// <internalonly/>
2418         /// <devdoc>
2419         /// <para>Gathers information about the control and delivers it to the <see cref='System.Web.UI.Page.Trace'/>
2420         /// property to be displayed when tracing is enabled for the page.</para>
2421         /// </devdoc>
BuildProfileTree(string parentId, bool calcViewState)2422         protected void BuildProfileTree(string parentId, bool calcViewState) {
2423             // estimate the viewstate size.
2424             calcViewState = calcViewState && (!flags[disableViewState]);
2425             int viewstatesize;
2426             if (calcViewState)
2427                 viewstatesize = EstimateStateSize(SaveViewState());
2428             else
2429                 viewstatesize = 0;
2430 
2431             int controlstatesize = 0;
2432             if(Page != null && Page._registeredControlsRequiringControlState != null && Page._registeredControlsRequiringControlState.Contains(this)) {
2433                 controlstatesize = EstimateStateSize(SaveControlStateInternal());
2434             }
2435 
2436             // give it all to the profiler
2437             Page.Trace.AddNewControl(UniqueID, parentId, this.GetType().FullName, viewstatesize, controlstatesize);
2438 
2439             if (_controls != null) {
2440                 int controlCount = _controls.Count;
2441                 for (int i = 0; i < controlCount; i++) {
2442                     _controls[i].BuildProfileTree(UniqueID, calcViewState);
2443                 }
2444             }
2445         }
2446 
2447 
SaveControlStateInternal()2448         internal object SaveControlStateInternal() {
2449             object controlState = SaveControlState();
2450             object adapterControlState = null;
2451             if (AdapterInternal != null) {
2452                 adapterControlState = AdapterInternal.SaveAdapterControlState();
2453             }
2454             if (controlState != null || adapterControlState != null) {
2455                 return new Pair(controlState, adapterControlState);
2456             }
2457             return null;
2458         }
2459 
2460 
2461         /// <devdoc>
2462         /// Save the control state, which is the essential state information needed even if view state is disabled.
2463         /// </devdoc>
SaveControlState()2464         protected internal virtual object SaveControlState() {
2465             return null;
2466         }
2467 
2468         // Save modified state the control would like restored on the postback.
2469         // Return null if there is no state to save.
2470 
2471         /// <devdoc>
2472         ///    <para>
2473         ///       Saves view state for use with a later <see cref='System.Web.UI.Control.LoadViewState'/>
2474         ///       request.
2475         ///    </para>
2476         /// </devdoc>
SaveViewState()2477         protected virtual object SaveViewState() {
2478             // Save values cached out of view state
2479             if (flags[visibleDirty]) {
2480                 ViewState["Visible"] = !flags[invisible];
2481             }
2482             if (flags[validateRequestModeDirty]) {
2483                 ViewState["ValidateRequestMode"] = (int)ValidateRequestMode;
2484             }
2485             if (_viewState != null)
2486                 return _viewState.SaveViewState();
2487 
2488             return null;
2489         }
2490 
2491         // Answer any state this control or its descendants want to save on freeze.
2492         // The format for saving is Triplet(myState, ArrayList childIDs, ArrayList childStates),
2493         // where myState or childStates and childIDs may be null.
SaveViewStateRecursive(ViewStateMode inheritedMode)2494         internal object SaveViewStateRecursive(ViewStateMode inheritedMode) {
2495             if (flags[disableViewState])
2496                 return null;
2497 
2498             bool saveThisState;
2499             if (flags[viewStateNotInherited]) {
2500                 if (flags[viewStateMode]) {
2501                     saveThisState = true;
2502                     inheritedMode = ViewStateMode.Enabled;
2503                 }
2504                 else {
2505                     saveThisState = false;
2506                     inheritedMode = ViewStateMode.Disabled;
2507                 }
2508             }
2509             else {
2510                 saveThisState = (inheritedMode == ViewStateMode.Enabled);
2511             }
2512 
2513             object adapterState = null;
2514             object controlSavedState = null;
2515 
2516             if (saveThisState) {
2517                 if (AdapterInternal != null) {
2518                     adapterState = AdapterInternal.SaveAdapterViewState();
2519                 }
2520                 controlSavedState = SaveViewState();
2521             }
2522 
2523             ArrayList childStates = null;
2524             if (HasControls()) {
2525                 ControlCollection occasionalFieldControls = _controls;
2526                 int occasionalFieldControlCount = occasionalFieldControls.Count;
2527 
2528                 bool useId = LoadViewStateByID;
2529                 for (int i = 0; i < occasionalFieldControlCount; i++) {
2530                     Control child = occasionalFieldControls[i];
2531                     object childState = child.SaveViewStateRecursive(inheritedMode);
2532                     if (childState != null) {
2533                         if (childStates == null) {
2534                             childStates = new ArrayList(occasionalFieldControlCount);
2535                         }
2536 
2537                         if (useId) {
2538                             child.EnsureID();
2539                             childStates.Add(child.ID);
2540                         }
2541                         else {
2542                             childStates.Add(i);
2543                         }
2544                         childStates.Add(childState);
2545                     }
2546                 }
2547             }
2548 
2549             if (AdapterInternal != null) {
2550                 if ((controlSavedState != null) || (adapterState != null) || (childStates != null)) {
2551                     return new Triplet(controlSavedState, adapterState, childStates);
2552                 }
2553             }
2554             else {
2555                 if ((controlSavedState != null) || (childStates != null)) {
2556                     return new Pair(controlSavedState, childStates);
2557                 }
2558             }
2559 
2560             return null;
2561         }
2562 
2563 
2564         /// <devdoc>
2565         /// <para>Outputs control content to a provided HTMLTextWriter
2566         /// output stream.</para>
2567         /// </devdoc>
Render(HtmlTextWriter writer)2568         protected internal virtual void Render(HtmlTextWriter writer) {
2569             RenderChildren(writer);
2570         }
2571 
RenderChildrenInternal(HtmlTextWriter writer, ICollection children)2572         internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children) {
2573             // If we have a delegate, use it for the rendering.
2574             // This happens when there is some ASP code.  See also Whidbey 33012.
2575             if(RareFields != null && RareFields.RenderMethod != null ) {
2576                 writer.BeginRender();
2577                 RareFields.RenderMethod(writer, this);
2578                 writer.EndRender();
2579                 return;
2580             }
2581             if (children != null) {
2582                 foreach (Control child in children) {
2583                     child.RenderControl(writer);
2584                 }
2585             }
2586         }
2587 
RenderChildren(HtmlTextWriter writer)2588         protected internal virtual void RenderChildren(HtmlTextWriter writer) {
2589             ICollection children = _controls;
2590             RenderChildrenInternal(writer, children);
2591         }
2592 
2593         /// <devdoc>
2594         ///    <para>[To be supplied.]</para>
2595         /// </devdoc>
RenderControl(HtmlTextWriter writer)2596         public virtual void RenderControl(HtmlTextWriter writer) {
2597             //use the Adapter property to ensure it is resolved
2598             RenderControl(writer, Adapter);
2599         }
2600 
2601         /// <devdoc>
2602         ///    <para>Used for MobilePage implementation.</para>
2603         /// </devdoc>
RenderControl(HtmlTextWriter writer, ControlAdapter adapter)2604         protected void RenderControl(HtmlTextWriter writer, ControlAdapter adapter) {
2605             if (!flags[invisible] && !flags[notVisibleOnPage]) {
2606                 HttpContext context = (Page == null) ? null : Page._context;
2607                 if (context  != null && context.TraceIsEnabled) {
2608                     int presize = context.Response.GetBufferedLength();
2609                     RenderControlInternal(writer, adapter);
2610                     int postsize = context.Response.GetBufferedLength();
2611                     context.Trace.AddControlSize(UniqueID, postsize - presize);
2612                 }
2613                 else {
2614                     RenderControlInternal(writer, adapter);
2615                 }
2616             }
2617             else {
2618                 TraceNonRenderingControlInternal(writer);
2619             }
2620         }
2621 
RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)2622         private void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) {
2623             try {
2624                 BeginRenderTracing(writer, this);
2625 
2626                 if (adapter != null) {
2627                     //
2628                     adapter.BeginRender(writer);
2629                     adapter.Render(writer);
2630                     adapter.EndRender(writer);
2631                 }
2632                 else {
2633                     Render(writer);
2634                 }
2635             }
2636             finally {
2637                 EndRenderTracing(writer, this);
2638             }
2639         }
2640 
2641 
2642         /// <devdoc>
2643         ///    <para>[To be supplied.]</para>
2644         /// </devdoc>
OnUnload(EventArgs e)2645         protected internal virtual void OnUnload(EventArgs e) {
2646             if(HasEvents()) {
2647                 EventHandler handler = _events[EventUnload] as EventHandler;
2648                 if (handler != null) {
2649                     handler(this, e);
2650                 }
2651             }
2652         }
2653 
2654 
2655         /// <devdoc>
2656         ///    <para>Enables a control to perform final cleanup.</para>
2657         /// </devdoc>
Dispose()2658         public virtual void Dispose() {
2659             IContainer container = null;
2660 
2661             if (Site != null) {
2662                 container = (IContainer)Site.GetService(typeof(IContainer));
2663                 if (container != null) {
2664                     container.Remove(this);
2665                     EventHandler disp = Events[EventDisposed] as EventHandler;
2666                     if (disp != null)
2667                         disp(this, EventArgs.Empty);
2668                 }
2669             }
2670 
2671             if (_occasionalFields != null) {
2672                 _occasionalFields.Dispose();
2673                 //do not null out for backwards compat, VSWhidbey 475940
2674                 //_occasionalFields = null;
2675             }
2676 
2677             if (_events != null) {
2678                 _events.Dispose();
2679                 _events = null;
2680             }
2681         }
2682 
2683 
UnloadRecursive(bool dispose)2684         internal virtual void UnloadRecursive(bool dispose) {
2685             Page page = Page;
2686             if (page != null && page.RequiresControlState(this)) {
2687                 page.UnregisterRequiresControlState(this);
2688                 RareFieldsEnsured.RequiredControlState = true;
2689             }
2690 
2691             // Remove the generated ID so it will be assigned a different ID next time.
2692             if (flags[useGeneratedID]) {
2693                 _id = null;
2694                 flags.Clear(useGeneratedID);
2695             }
2696 
2697             if (_controls != null) {
2698                 string oldmsg = _controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
2699 
2700                 int controlCount = _controls.Count;
2701                 for (int i = 0; i < controlCount; i++)
2702                     _controls[i].UnloadRecursive(dispose);
2703 
2704                 _controls.SetCollectionReadOnly(oldmsg);
2705             }
2706 
2707             if (AdapterInternal != null) {
2708                 AdapterInternal.OnUnload(EventArgs.Empty);
2709             }
2710             else {
2711                 OnUnload(EventArgs.Empty);
2712             }
2713 
2714             //
2715             if (dispose)
2716                 Dispose();
2717 
2718             // VSWhidbey 244999: Everett behavior doesn't reset the control state.
2719             // But for control which requires its OnInit method to be called again
2720             // to properly initialize when the control is removed and added back
2721             // to Page's control tree, the control can override IsReloadable
2722             // to true so the control state is reset.  e.g. Validator, see bug
2723             if (IsReloadable) {
2724                 _controlState = ControlState.Constructed;
2725             }
2726         }
2727 
2728 
2729         /// <devdoc>
2730         ///    <para>Assigns an sources of the event and its information up the page control
2731         ///       hierarchy until they reach the top of the control tree. </para>
2732         /// </devdoc>
RaiseBubbleEvent(object source, EventArgs args)2733         protected void RaiseBubbleEvent(object source, EventArgs args) {
2734             Control currentTarget = Parent;
2735             while (currentTarget != null) {
2736                 if (currentTarget.OnBubbleEvent(source, args)) {
2737                     return;
2738                 }
2739                 currentTarget = currentTarget.Parent;
2740             }
2741         }
2742 
2743 
2744         /// <devdoc>
2745         ///    <para>Determines whether the event for the control should be passed up the page's
2746         ///       control hierarchy.</para>
2747         /// </devdoc>
OnBubbleEvent(object source, EventArgs args)2748         protected virtual bool OnBubbleEvent(object source, EventArgs args) {
2749             return false;
2750         }
2751 
2752 
2753         // Members related to being a container
2754 
2755 
2756         /// <devdoc>
2757         ///    <para> Gets a ControlCollection object that represents the child controls for a specified control in the
2758         ///       UI hierarchy.</para>
2759         /// </devdoc>
2760         [
2761         Browsable(false),
2762         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
2763         WebSysDescription(SR.Control_Controls)
2764         ]
2765         public virtual ControlCollection Controls {
2766             get {
2767                 if (_controls == null) {
2768                     _controls = CreateControlCollection();
2769                 }
2770                 return _controls;
2771             }
2772         }
2773 
2774         [
2775         WebCategory("Behavior"),
2776         WebSysDescription(SR.Control_ValidateRequestMode),
2777         DefaultValue(ValidateRequestMode.Inherit)
2778         ]
2779         public virtual ValidateRequestMode ValidateRequestMode {
2780             get {
2781                 return (ValidateRequestMode)flags[validateRequestMode, validateRequestModeOffset];
2782             }
2783             set {
2784                 SetValidateRequestModeInternal(value, setDirty: true);
2785             }
2786         }
2787 
SetValidateRequestModeInternal(UI.ValidateRequestMode value, bool setDirty)2788         internal void SetValidateRequestModeInternal(UI.ValidateRequestMode value, bool setDirty) {
2789             if (value < ValidateRequestMode.Inherit || value > ValidateRequestMode.Enabled) {
2790                 throw new ArgumentOutOfRangeException("value");
2791             }
2792 
2793             int oldValue = flags[validateRequestMode, validateRequestModeOffset];
2794             if (setDirty && (oldValue != (int)value)) {
2795                 flags.Set(validateRequestModeDirty);
2796             }
2797 
2798             flags[validateRequestMode, validateRequestModeOffset] = (int)value;
2799         }
2800 
CalculateEffectiveValidateRequest()2801         internal bool CalculateEffectiveValidateRequest() {
2802             RuntimeConfig config = RuntimeConfig.GetConfig();
2803             HttpRuntimeSection runtimeSection = config.HttpRuntime;
2804             if (runtimeSection.RequestValidationMode >= VersionUtil.Framework45) {
2805                 Control c = this;
2806                 while (c != null) {
2807                     ValidateRequestMode mode = c.ValidateRequestMode;
2808                     if (mode != ValidateRequestMode.Inherit) {
2809                         return mode == ValidateRequestMode.Enabled;
2810                     }
2811                     c = c.Parent;
2812                 }
2813             }
2814             return true;
2815         }
2816 
2817 
2818         /// <devdoc>
2819         ///    <para>Indicates a dictionary of state information that allows you to save and restore
2820         ///       the state of a control across multiple requests for the same page.</para>
2821         /// </devdoc>
2822         [
2823         Browsable(false),
2824         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
2825         WebSysDescription(SR.Control_State)
2826         ]
2827         protected virtual StateBag ViewState {
2828             get {
2829                 if (_viewState != null) {   // create a StateBag on demand; WebControl makes its case sensitive
2830                     return _viewState;
2831                 }
2832 
2833                 _viewState = new StateBag(ViewStateIgnoresCase);
2834                 if (IsTrackingViewState)
2835                     _viewState.TrackViewState();
2836                 return _viewState;
2837             }
2838         }
2839 
2840         // fast enough that we cam always use it.
2841 
2842         /// <devdoc>
2843         /// <para>Indicates whether the <see cref='System.Web.UI.StateBag'/> object is case-insensitive.</para>
2844         /// </devdoc>
2845         [
2846         Browsable(false),
2847         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
2848         ]
2849         protected virtual bool ViewStateIgnoresCase {
2850             get {
2851                 return false;
2852             }
2853         }
2854 
2855 
2856         /// <devdoc>
2857         /// </devdoc>
AddedControl(Control control, int index)2858         protected internal virtual void AddedControl(Control control, int index) {
2859             if (control.OwnerControl != null) {
2860                 throw new InvalidOperationException(SR.GetString(SR.Substitution_NotAllowed));
2861             }
2862 
2863             if (control._parent != null) {
2864                 control._parent.Controls.Remove(control);
2865             }
2866 
2867             control._parent = this;
2868             control._page = Page;
2869             control.flags.Clear(designModeChecked);
2870 
2871             // We only add to naming container if it is available. Otherwise, it will be pushed through
2872             // during InitRecursive
2873             Control namingContainer = flags[isNamingContainer] ? this : _namingContainer;
2874             if (namingContainer != null) {
2875                 control.UpdateNamingContainer(namingContainer);
2876                 if (control._id == null && !control.flags[idNotRequired]) {
2877                     // this will also dirty the name table in the naming container
2878                     control.GenerateAutomaticID();
2879                 }
2880                 else if (control._id != null || (control._controls != null)) {
2881                     // If the control has and ID, or has children (which *may* themselves
2882                     // have ID's), we need to dirty the name table (ASURT 100557)
2883                     namingContainer.DirtyNameTable();
2884                 }
2885             }
2886 
2887             /*
2888              * The following is for times when AddChild is called after CreateChildControls. This
2889              * allows users to add children at any time in the creation process without having
2890              * to understand the underlying machinery.
2891              * Note that if page is null, it means we haven't been attached to a container ourselves.
2892              * If this is true, when we are, our children will be recursively set up.
2893              */
2894             if (_controlState >= ControlState.ChildrenInitialized) {
2895 
2896                 Debug.Assert(namingContainer != null);
2897                 control.InitRecursive(namingContainer);
2898 
2899                 // VSWhidbey 396372: We need to reregister the control state if the control is reparented because the control
2900                 // is unregistered during unload, but its already been inited once, so it will not get its Init called again
2901                 // which is where most controls call RegisterRequiresControlState
2902                 if (control._controlState >= ControlState.Initialized &&
2903                     control.RareFields != null &&
2904                     control.RareFields.RequiredControlState) {
2905                     Page.RegisterRequiresControlState(control);
2906                 }
2907 
2908                 if (_controlState >= ControlState.ViewStateLoaded) {
2909                     object viewState = null;
2910                     if(_occasionalFields != null && _occasionalFields.ControlsViewState != null) {
2911                         viewState = _occasionalFields.ControlsViewState[index];
2912                         // This solution takes the conservative approach that once viewstate has been
2913                         // applied to a child control, it is thrown away.  This eliminates inadvertently
2914                         // setting viewstate on the wrong control, which can occur in scenarios where
2915                         // the child control collection is being manipulated via code.  Probably need
2916                         // to provide a feature where programmer can control whether to reapply viewstate
2917                         // or not.
2918                         if (LoadViewStateByID) {
2919                             control.EnsureID();
2920                             viewState = _occasionalFields.ControlsViewState[control.ID];
2921                             _occasionalFields.ControlsViewState.Remove(control.ID);
2922                         }
2923                         else {
2924                             viewState = _occasionalFields.ControlsViewState[index];
2925                             _occasionalFields.ControlsViewState.Remove(index);
2926                         }
2927                     }
2928 
2929                     control.LoadViewStateRecursive(viewState);
2930 
2931                     if (_controlState >= ControlState.Loaded) {
2932                         control.LoadRecursive();
2933 
2934                         if (_controlState >= ControlState.PreRendered)
2935                             control.PreRenderRecursiveInternal();
2936                     }
2937                 }
2938             }
2939         }
2940 
2941 
2942         /// <devdoc>
2943         ///    <para>[To be supplied.]</para>
2944         /// </devdoc>
CreateControlCollection()2945         protected virtual ControlCollection CreateControlCollection() {
2946             return new ControlCollection(this);
2947         }
2948 
2949 
2950         /// <devdoc>
2951         ///    <para>
2952         ///       Notifies any controls that use composition-based implementation to create any
2953         ///       child controls they contain in preperation for postback or rendering.
2954         ///    </para>
2955         /// </devdoc>
CreateChildControls()2956         protected internal virtual void CreateChildControls() {
2957         }
2958 
2959 
2960 
2961         /// <devdoc>
2962         ///    <para>Indicates whether the control's child controls have been created.</para>
2963         /// </devdoc>
2964         protected bool ChildControlsCreated {
2965             get {
2966                 return flags[controlsCreated];
2967             }
2968             set {
2969                 if (!value && flags[controlsCreated]) {
2970                     Controls.Clear();
2971                 }
2972                 if(value) {
2973                     flags.Set(controlsCreated);
2974                 }
2975                 else {
2976                     flags.Clear(controlsCreated);
2977                 }
2978             }
2979         }
2980 
2981 
2982         /// <devdoc>
2983         ///    <para>Make a URL absolute using the AppRelativeTemplateSourceDirectory.  The returned URL is for
2984         ///        client use, and will contain the session cookie if appropriate.</para>
2985         /// </devdoc>
ResolveUrl(string relativeUrl)2986         public string ResolveUrl(string relativeUrl) {
2987             if (relativeUrl == null) {
2988                 throw new ArgumentNullException("relativeUrl");
2989             }
2990 
2991             // check if its empty or already absolute
2992             if ((relativeUrl.Length == 0) || (UrlPath.IsRelativeUrl(relativeUrl) == false)) {
2993                 return relativeUrl;
2994             }
2995 
2996             string baseUrl = AppRelativeTemplateSourceDirectory;
2997             if (String.IsNullOrEmpty(baseUrl)) {
2998                 return relativeUrl;
2999             }
3000 
3001             // first make it absolute
3002             string url = UrlPath.Combine(baseUrl, relativeUrl);
3003 
3004             // include the session cookie if available (ASURT 47658)
3005             // As a side effect, this will change an app relative path (~/...) to app absolute
3006             return Context.Response.ApplyAppPathModifier(url);
3007         }
3008 
3009 
3010         /// <devdoc>
3011         ///    <para> Return a URL that is suitable for use on the client.
3012         ///     If the URL is absolute, return it unchanged.  If it is relative, turn it into a
3013         ///     relative URL that is correct from the point of view of the current request path
3014         ///     (which is what the browser uses for resolution).</para>
3015         /// </devdoc>
ResolveClientUrl(string relativeUrl)3016         public string ResolveClientUrl(string relativeUrl) {
3017             if (DesignMode && Page != null && Page.Site != null) {
3018                 IUrlResolutionService resolutionService = (IUrlResolutionService)Page.Site.GetService(typeof(IUrlResolutionService));
3019                 if (resolutionService != null) {
3020                     return resolutionService.ResolveClientUrl(relativeUrl);
3021                 }
3022             }
3023 
3024             if (relativeUrl == null) {
3025                 throw new ArgumentNullException("relativeUrl");
3026             }
3027 
3028             // Get the app absolute TemplateSourceDirectory (not app relative)
3029             string tplSourceDir = VirtualPath.GetVirtualPathString(TemplateControlVirtualDirectory);
3030             if (String.IsNullOrEmpty(tplSourceDir))
3031                 return relativeUrl;
3032 
3033             string baseRequestDir = Context.Request.ClientBaseDir.VirtualPathString;
3034 
3035             // If the path is app relative (~/...), we cannot take shortcuts, since
3036             // the ~ is meaningless on the client, and must be resolved
3037             if (!UrlPath.IsAppRelativePath(relativeUrl)) {
3038 
3039                 // If the template source directory is the same as the directory of the request,
3040                 // we don't need to do any adjustments to the input path
3041                 if (StringUtil.EqualsIgnoreCase(baseRequestDir, tplSourceDir))
3042                     return relativeUrl;
3043 
3044                 // check if it's empty or absolute
3045                 if ((relativeUrl.Length == 0) || (!UrlPath.IsRelativeUrl(relativeUrl))) {
3046                     return relativeUrl;
3047                 }
3048             }
3049 
3050             // first make it absolute
3051             string url = UrlPath.Combine(tplSourceDir, relativeUrl);
3052 
3053             // Make sure the path ends with a slash before calling MakeRelative
3054             baseRequestDir = UrlPath.AppendSlashToPathIfNeeded(baseRequestDir);
3055 
3056             // Now, make it relative to the current request, so that the client will
3057             // compute the correct path
3058             url = HttpUtility.UrlPathEncode(UrlPath.MakeRelative(baseRequestDir, url));
3059             Debug.Trace("ClientUrl", "*** ResolveClientUrl (" + relativeUrl + ") --> " + url + " ***");
3060             return url;
3061         }
3062 
DirtyNameTable()3063         internal void DirtyNameTable() {
3064             Debug.Assert(this is INamingContainer);
3065             if(_occasionalFields != null) {
3066                 _occasionalFields.NamedControls = null;
3067             }
3068         }
3069 
EnsureNamedControlsTable()3070         private void EnsureNamedControlsTable() {
3071             Debug.Assert(this is INamingContainer);
3072             Debug.Assert(HasControls());
3073             Debug.Assert(_occasionalFields != null);
3074             Debug.Assert(_occasionalFields.NamedControls == null);
3075 
3076             _occasionalFields.NamedControls = new HybridDictionary(/*initialSize*/ _occasionalFields.NamedControlsID, /*caseInsensitive*/ true);
3077             FillNamedControlsTable(this, _controls);
3078         }
3079 
FillNamedControlsTable(Control namingContainer, ControlCollection controls)3080         private void FillNamedControlsTable(Control namingContainer, ControlCollection controls) {
3081             Debug.Assert(namingContainer._occasionalFields != null);
3082             Debug.Assert(namingContainer._occasionalFields.NamedControls != null);
3083             Debug.Assert((controls != null) && (controls.Count != 0));
3084 
3085             int controlCount = controls.Count;
3086             for (int i=0; i < controlCount; i++) {
3087                 Control control = controls[i];
3088                 if (control._id != null) {
3089 #if DEBUG
3090                     if (control._namingContainer != null) {
3091                         Debug.Assert(control._namingContainer == namingContainer);
3092                     }
3093 #endif // DEBUG
3094                     try {
3095                         namingContainer.EnsureOccasionalFields();
3096                         namingContainer._occasionalFields.NamedControls.Add(control._id, control);
3097                     }
3098                     catch {
3099                         throw new HttpException(SR.GetString(SR.Duplicate_id_used, control._id, "FindControl"));
3100                     }
3101                 }
3102                 if (control.HasControls() && (control.flags[isNamingContainer] == false)) {
3103                     FillNamedControlsTable(namingContainer, control.Controls);
3104                 }
3105             }
3106         }
3107 
3108 
3109         /// <devdoc>
3110         ///    <para>Searches the current naming container for a control with
3111         ///       the specified <paramref name="id"/> .</para>
3112         /// </devdoc>
FindControl(String id)3113         public virtual Control FindControl(String id) {
3114             return FindControl(id, 0);
3115         }
3116 
3117 
3118         /// <internalonly/>
3119         /// <devdoc>
3120         ///    <para>Searches the current naming container for a control with the specified
3121         ///    <paramref name="id"/> and an offset to aid in the
3122         ///       search.</para>
3123         /// </devdoc>
FindControl(String id, int pathOffset)3124         protected virtual Control FindControl(String id, int pathOffset) {
3125             // DevDiv #338426 - Since this is a recursive function, malicious clients can send us an id
3126             // which causes a very deep stack dive, resulting in SO (which terminates the worker process).
3127             // We avoid this via the following call, which at the time of this writing ensures that at
3128             // least 50% of the available stack remains. The check is very quick: < 1 microsecond.
3129             RuntimeHelpers.EnsureSufficientExecutionStack();
3130 
3131             string childID;
3132 
3133             EnsureChildControls();
3134 
3135             // If we're not the naming container, let it do the job
3136             if (!(flags[isNamingContainer])) {
3137                 Control namingContainer = NamingContainer;
3138                 if (namingContainer != null) {
3139                     return namingContainer.FindControl(id, pathOffset);
3140                 }
3141                 return null;
3142             }
3143 
3144             // No registered control, demand create the named controls table
3145             //call HasControls doesn't ensures _occasionalFields != null
3146             if (HasControls()) {
3147                 EnsureOccasionalFields();
3148                 if (_occasionalFields.NamedControls == null) {
3149                     EnsureNamedControlsTable();
3150                 }
3151             }
3152             if (_occasionalFields == null || _occasionalFields.NamedControls == null) {
3153                 return null;
3154             }
3155 
3156             // Need to support ':' for V1 backward compatibility.
3157             char[] findControlSeparators = { ID_SEPARATOR, LEGACY_ID_SEPARATOR };
3158 
3159             // Is it a hierarchical name?
3160             int newPathOffset = id.IndexOfAny(findControlSeparators, pathOffset);
3161 
3162             // If not, handle it here
3163             if (newPathOffset == -1) {
3164                 childID = id.Substring(pathOffset);
3165                 return _occasionalFields.NamedControls[childID] as Control;
3166             }
3167 
3168             // Get the name of the child, and try to locate it
3169             childID = id.Substring(pathOffset, newPathOffset - pathOffset);
3170             Control child =  _occasionalFields.NamedControls[childID] as Control;
3171 
3172             // Child doesn't exist: fail
3173             if (child == null)
3174                 return null;
3175 
3176             return child.FindControl(id, newPathOffset + 1);
3177         }
3178 
FindControlFromPageIfNecessary(string id)3179         internal Control FindControlFromPageIfNecessary(string id) {
3180             Control c = FindControl(id);
3181             // Find control from the page if it's a hierarchical ID.
3182             // Dev11 bug 19915
3183             if (c == null && Page != null) {
3184                 char[] findControlSeparators = { ID_SEPARATOR, LEGACY_ID_SEPARATOR };
3185                 if (id.IndexOfAny(findControlSeparators) != -1) {
3186                     c = Page.FindControl(id);
3187                 }
3188             }
3189             return c;
3190         }
3191 
3192         /*
3193          * Called when the controls of a naming container are cleared.
3194          */
ClearNamingContainer()3195         internal void ClearNamingContainer() {
3196             Debug.Assert(this is INamingContainer);
3197 
3198             EnsureOccasionalFields();
3199             _occasionalFields.NamedControlsID = 0;
3200             DirtyNameTable();
3201         }
3202 
3203 
3204         /// <internalonly/>
3205         /// <devdoc>
3206         /// </devdoc>
3207         [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
GetDesignModeState()3208         protected virtual IDictionary GetDesignModeState() {
3209             ControlRareFields rareFields = RareFieldsEnsured;
3210             if (rareFields.DesignModeState == null) {
3211                 rareFields.DesignModeState = new HybridDictionary();
3212             }
3213             return rareFields.DesignModeState;
3214         }
3215 
3216 
3217         /// <devdoc>
3218         ///    <para>Determines if the current control contains any child
3219         ///       controls. Since this method simply deteremines if any child controls exist at
3220         ///       all, it can enhance performance by avoiding a call to the Count property,
3221         ///       inherited from the <see cref='System.Web.UI.ControlCollection'/> class, on the <see cref='System.Web.UI.Control.Controls'/>
3222         ///       property.</para>
3223         /// </devdoc>
HasControls()3224         public virtual bool HasControls() {
3225             return _controls != null && _controls.Count > 0;
3226         }
3227 
3228         /*
3229          * Check if a Control either has children or has a compiled render method.
3230          * This is to address issues like ASURT 94127
3231          */
HasRenderingData()3232         internal bool HasRenderingData() {
3233             return HasControls() || HasRenderDelegate();
3234         }
3235 
3236         /*
3237          * Check if a Control either has children or has a compiled render method.
3238          * This is to address issues like ASURT 94127
3239          */
HasRenderDelegate()3240         internal bool HasRenderDelegate() {
3241             if(RareFields != null) {
3242                 return (RareFields.RenderMethod != null );
3243             }
3244             return false;
3245         }
3246 
3247         /*
3248          * Returns true if the container contains just a static string, i.e.,
3249          * when the Controls collection has a single LiteralControl.
3250          */
3251 
3252         /// <devdoc>
3253         ///    <para>Determines if the container holds literal content only.
3254         ///       When this method returns <see langword='true'/>
3255         ///       , the container collection only holds a single literal control. The
3256         ///       content is then passed to the requesting browser as HTML.</para>
3257         /// </devdoc>
IsLiteralContent()3258         protected bool IsLiteralContent() {
3259             return (_controls != null) && (_controls.Count == 1) &&
3260             ((_controls[0] is LiteralControl));
3261         }
3262 
3263 
3264         /// <devdoc>
3265         ///    <para>Determines if view state changes to the
3266         ///    <see langword='Control'/>
3267         ///    are being saved. </para>
3268         /// </devdoc>
3269         protected bool IsTrackingViewState {
3270             get {
3271                 return flags[marked];
3272             }
3273         }
3274 
3275 
3276         /// <devdoc>
3277         ///    <para>Turns on tracking of view state changes to the control
3278         ///       so that they can be stored in the <see langword='StateBag'/>
3279         ///       object.</para>
3280         /// </devdoc>
TrackViewState()3281         protected virtual void TrackViewState() {
3282             if (_viewState != null)
3283                 _viewState.TrackViewState();
3284 
3285             flags.Set(marked);
3286         }
3287 
3288 
3289         /// <devdoc>
3290         ///    <para>Checks that the control contains child controls; if it does not, it creates
3291         ///       them. This includes any literal content being parsed as a <see cref='System.Web.UI.LiteralControl'/>
3292         ///       object. </para>
3293         /// </devdoc>
EnsureChildControls()3294         protected virtual void EnsureChildControls() {
3295             if (!ChildControlsCreated && !flags[creatingControls]) {
3296                 flags.Set(creatingControls);
3297                 try {
3298                     ResolveAdapter();
3299                     if (AdapterInternal != null) {
3300                         AdapterInternal.CreateChildControls();
3301                     }
3302                     else {
3303                         CreateChildControls();
3304                     }
3305 
3306                     // Only set ChildControlsCreated = true if CreateChildControls() did not throw
3307                     // an exception (VSWhidbey 465798).
3308                     ChildControlsCreated = true;
3309                 }
3310                 finally {
3311                     flags.Clear(creatingControls);
3312                 }
3313             }
3314         }
3315 
3316         /// <devdoc>
3317         /// Used internally to store a ControlBuilder reference for the control.
3318         /// The builder will be used at design-time to help persist all the filtered properties
3319         /// of the control.
3320         /// </devdoc>
SetControlBuilder(ControlBuilder controlBuilder)3321         internal void SetControlBuilder(ControlBuilder controlBuilder) {
3322             RareFieldsEnsured.ControlBuilder = controlBuilder;
3323         }
3324 
3325 
3326         /// <devdoc>
3327         /// </devdoc>
RemovedControl(Control control)3328         protected internal virtual void RemovedControl(Control control) {
3329             if (control.OwnerControl != null) {
3330                 throw new InvalidOperationException(SR.GetString(SR.Substitution_NotAllowed));
3331             }
3332 
3333             if ((_namingContainer != null) && (control._id != null)) {
3334                 _namingContainer.DirtyNameTable();
3335             }
3336 
3337             // Controls may need to do their own cleanup.
3338             control.UnloadRecursive(false);
3339 
3340             control._parent = null;
3341             control._page = null;
3342             control._namingContainer = null;
3343 
3344             // Don't reset template source virtual directory on TemplateControl's, because
3345             // the path is their own, not their parent. i.e. it doesn't change no matter
3346             // where in the tree they end up.
3347             if (!(control is TemplateControl)) {
3348                 if (control._occasionalFields != null) {
3349                     control._occasionalFields.TemplateSourceVirtualDirectory = null;
3350                 }
3351             }
3352 
3353             if (control._occasionalFields != null ) {
3354                 control._occasionalFields.TemplateControl = null;
3355             }
3356 
3357             control.flags.Clear(mustRenderID);
3358             control.ClearCachedUniqueIDRecursive();
3359         }
3360 
SetDesignMode()3361         internal void SetDesignMode() {
3362             flags.Set(designMode);
3363             flags.Set(designModeChecked);
3364         }
3365 
3366 
3367         /// <internalonly/>
3368         /// <devdoc>
3369         /// </devdoc>
SetDesignModeState(IDictionary data)3370         protected virtual void SetDesignModeState(IDictionary data) {
3371         }
3372 
3373         // Set the delegate to the render method
3374 
3375         /// <internalonly/>
3376         /// <devdoc>
3377         ///    <para>Assigns any event handler delegates for the control to match the parameters
3378         ///       defined in the <see cref='System.Web.UI.RenderMethod'/>. </para>
3379         /// </devdoc>
3380         [EditorBrowsable(EditorBrowsableState.Advanced)]
SetRenderMethodDelegate(RenderMethod renderMethod)3381         public void SetRenderMethodDelegate(RenderMethod renderMethod) {
3382             RareFieldsEnsured.RenderMethod = renderMethod;
3383 
3384             // Make the collection readonly if there are code blocks (ASURT 78810)
3385             Controls.SetCollectionReadOnly(SR.Collection_readonly_Codeblocks);
3386         }
3387 
3388 
3389         /// <internalonly/>
3390         /// <devdoc>
3391         ///    <para>Returns whether the control contains any data binding logic. This method is
3392         ///       only accessed by RAD designers.</para>
3393         /// </devdoc>
3394         bool IDataBindingsAccessor.HasDataBindings {
3395             get {
3396                 return ((RareFields != null) && (RareFields.DataBindings != null) && (RareFields.DataBindings.Count != 0));
3397             }
3398         }
3399 
3400 
3401         /// <internalonly/>
3402         /// <devdoc>
3403         /// <para>Indicates a collection of all data bindings on the control. This property is
3404         /// read-only.</para>
3405         /// </devdoc>
3406         DataBindingCollection IDataBindingsAccessor.DataBindings {
3407             get {
3408                 ControlRareFields rareFields = RareFieldsEnsured;
3409                 if (rareFields.DataBindings == null) {
3410                     rareFields.DataBindings = new DataBindingCollection();
3411                 }
3412                 return rareFields.DataBindings;
3413             }
3414         }
3415 
3416 
3417         // IParserAccessor interface
3418         // A sub-object tag was parsed by the parser; add it to this control.
3419 
3420         /// <internalonly/>
3421         /// <devdoc>
3422         /// <para>Notifies the control that an element, XML or HTML, was parsed, and adds it to
3423         /// the control.</para>
3424         /// </devdoc>
IParserAccessor.AddParsedSubObject(object obj)3425         void IParserAccessor.AddParsedSubObject(object obj) {
3426             AddParsedSubObject(obj);
3427         }
3428 
3429         internal string SpacerImageUrl {
3430             get {
3431                 EnsureOccasionalFields();
3432                 if (_occasionalFields.SpacerImageUrl == null) {
3433                     _occasionalFields.SpacerImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(WebControl), "Spacer.gif");
3434                 }
3435                 return _occasionalFields.SpacerImageUrl;
3436             }
3437         }
3438 
3439         private Control OwnerControl {
3440             get {
3441                 if (RareFields == null) {
3442                     return null;
3443                 }
3444 
3445                 return RareFields.OwnerControl;
3446             }
3447             set {
3448                 RareFieldsEnsured.OwnerControl = value;
3449             }
3450         }
3451 
3452         internal IPostBackDataHandler PostBackDataHandler {
3453             get {
3454                 IPostBackDataHandler pbdh = AdapterInternal as IPostBackDataHandler;
3455                 if(pbdh != null)
3456                     return pbdh;
3457                 pbdh = this as IPostBackDataHandler;
3458                 return pbdh;
3459             }
3460         }
3461 
3462         internal IPostBackEventHandler PostBackEventHandler {
3463             get {
3464                 IPostBackEventHandler pbeh = AdapterInternal as IPostBackEventHandler;
3465                 if(pbeh != null)
3466                     return pbeh;
3467                 pbeh = this as IPostBackEventHandler;
3468                 return pbeh;
3469             }
3470         }
3471 
3472         /// <summary>
3473         /// This method is used for design-time tracing of rendering data.
3474         /// </summary>
3475         [EditorBrowsable(EditorBrowsableState.Never)]
BeginRenderTracing(TextWriter writer, object traceObject)3476         protected void BeginRenderTracing(TextWriter writer, object traceObject) {
3477             RenderTraceListener.CurrentListeners.BeginRendering(writer, traceObject);
3478         }
3479 
3480         /// <summary>
3481         /// This method is used for design-time tracing of rendering data.
3482         /// </summary>
3483         [EditorBrowsable(EditorBrowsableState.Never)]
EndRenderTracing(TextWriter writer, object traceObject)3484         protected void EndRenderTracing(TextWriter writer, object traceObject) {
3485             RenderTraceListener.CurrentListeners.EndRendering(writer, traceObject);
3486         }
3487 
TraceNonRenderingControlInternal(TextWriter writer)3488         private void TraceNonRenderingControlInternal(TextWriter writer) {
3489             BeginRenderTracing(writer, this);
3490             EndRenderTracing(writer, this);
3491         }
3492 
3493         /// <summary>
3494         /// This method is used for design-time tracing of rendering data.
3495         /// </summary>
3496         [EditorBrowsable(EditorBrowsableState.Never)]
SetTraceData(object traceDataKey, object traceDataValue)3497         public void SetTraceData(object traceDataKey, object traceDataValue) {
3498             SetTraceData(this, traceDataKey, traceDataValue);
3499         }
3500 
3501         /// <summary>
3502         /// This method is used for design-time tracing of rendering data.
3503         /// </summary>
3504         [EditorBrowsable(EditorBrowsableState.Never)]
SetTraceData(object tracedObject, object traceDataKey, object traceDataValue)3505         public void SetTraceData(object tracedObject, object traceDataKey, object traceDataValue) {
3506             RenderTraceListener.CurrentListeners.SetTraceData(tracedObject, traceDataKey, traceDataValue);
3507         }
3508 
3509         #region IControlDesignerAccessor implementation
3510 
3511         /// <internalonly/>
3512         IDictionary IControlDesignerAccessor.UserData {
3513             get {
3514                 ControlRareFields rareFields = RareFieldsEnsured;
3515                 if (rareFields.ControlDesignerAccessorUserData == null) {
3516                     rareFields.ControlDesignerAccessorUserData = new HybridDictionary();
3517                 }
3518                 return rareFields.ControlDesignerAccessorUserData;
3519             }
3520         }
3521 
3522         /// <internalonly/>
3523         /// <devdoc>
3524         /// </devdoc>
IControlDesignerAccessor.GetDesignModeState()3525         IDictionary IControlDesignerAccessor.GetDesignModeState() {
3526             return GetDesignModeState();
3527         }
3528 
3529 
3530         /// <internalonly/>
3531         /// <devdoc>
3532         /// </devdoc>
IControlDesignerAccessor.SetDesignModeState(IDictionary data)3533         void IControlDesignerAccessor.SetDesignModeState(IDictionary data) {
3534             SetDesignModeState(data);
3535         }
3536 
IControlDesignerAccessor.SetOwnerControl(Control owner)3537         void IControlDesignerAccessor.SetOwnerControl(Control owner) {
3538             if (owner == this) {
3539                 throw new ArgumentException(SR.GetString(SR.Control_CannotOwnSelf), "owner");
3540             }
3541             OwnerControl = owner;
3542             _parent = owner.Parent;
3543             _page = owner.Page;
3544         }
3545         #endregion
3546 
3547         #region IControlBuilderAccessor implementation
3548 
3549         /// <internalonly/>
3550         /// <devdoc>
3551         /// A reference to the ControlBuilder that was used to construct this control (if there was one)
3552         /// </devdoc>
3553         [
3554         Browsable(false),
3555         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
3556         ]
3557         ControlBuilder IControlBuilderAccessor.ControlBuilder {
3558             get {
3559                 return RareFields != null ? RareFields.ControlBuilder : null;
3560             }
3561         }
3562         #endregion IControlBuilderAccessor implementation
3563 
3564         #region IExpressionsAccessor
3565 
3566 
3567         /// <internalonly/>
3568         bool IExpressionsAccessor.HasExpressions {
3569             get {
3570                 if (RareFields == null) {
3571                     return false;
3572                 }
3573                 ExpressionBindingCollection expressions = RareFields.ExpressionBindings;
3574                 return ((expressions != null) && (expressions.Count > 0));
3575             }
3576         }
3577 
3578 
3579         /// <internalonly/>
3580         ExpressionBindingCollection IExpressionsAccessor.Expressions {
3581             get {
3582                 ExpressionBindingCollection expressions = RareFieldsEnsured.ExpressionBindings;
3583                 if (expressions == null) {
3584                     expressions = new ExpressionBindingCollection();
3585                     RareFields.ExpressionBindings = expressions;
3586                 }
3587                 return expressions;
3588             }
3589         }
3590         #endregion
3591 
3592         private sealed class ControlRareFields : IDisposable {
3593 
ControlRareFields()3594             internal ControlRareFields() {
3595             }
3596             public ISite Site;
3597             public RenderMethod RenderMethod;
3598             // Reference to the ControlBuilder used to build this control
3599             public ControlBuilder ControlBuilder;
3600             public DataBindingCollection DataBindings;
3601             public Control OwnerControl;
3602             public ExpressionBindingCollection ExpressionBindings;
3603             public bool RequiredControlState = false;
3604 
3605             // These fields are only used in the designer so we
3606             // keep them here to prevent memory bloat at runtime
3607             public IDictionary ControlDesignerAccessorUserData;
3608             public IDictionary DesignModeState;
3609 
3610             public Version RenderingCompatibility;
3611             public RouteCollection RouteCollection;
3612             public ControlAdapter Adapter;
3613 
Dispose()3614             public void Dispose() {
3615                 //do not null out for backwards compat, VSWhidbey 475940
3616                 //Site = null;
3617                 //RenderMethod = null;
3618                 //DataBindings = null;
3619                 //OwnerControl = null;
3620                 //ExpressionBindings = null;
3621                 //Adapter = null;
3622                 ControlBuilder = null;
3623                 if (OwnerControl != null)
3624                 {
3625                     OwnerControl.Dispose();
3626                 }
3627                 ControlDesignerAccessorUserData = null;
3628                 DesignModeState = null;
3629                 RenderingCompatibility = null;
3630                 RouteCollection = null;
3631             }
3632         }
3633 
3634         private sealed class OccasionalFields : IDisposable {
OccasionalFields()3635             internal OccasionalFields() {
3636             }
3637 
3638             public string SkinId;
3639             public IDictionary ControlsViewState;
3640             public int NamedControlsID;
3641             // Only used if we are a naming container.  It contains all the controls
3642             // in the namespace.
3643             public IDictionary NamedControls;
3644             public ControlRareFields RareFields;
3645             public String UniqueIDPrefix;
3646 
3647             public string SpacerImageUrl;
3648             public TemplateControl TemplateControl;
3649             public VirtualPath TemplateSourceVirtualDirectory;
3650 
Dispose()3651             public void Dispose() {
3652                 if (RareFields != null) {
3653                     RareFields.Dispose();
3654                 }
3655 
3656                 ControlsViewState = null;
3657                 //do not null out for backwards compat, VSWhidbey 475940
3658                 //NamedControls = null;
3659                 //UniqueIDPrefix = null;
3660                 //TemplateControl = null;
3661                 //TemplateSourceVirtualDirectory = null;
3662             }
3663         }
3664     }
3665 }
3666