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