Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / xsp / System / Web / UI / Control.cs / 7 / Control.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Web.UI {
using System.Text;
using System.ComponentModel;
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
using System.IO;
using HttpException = System.Web.HttpException;
using System.Web.Configuration;
using System.Web.UI.Adapters;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.Util;
using System.Web.Hosting;
using System.Web.Caching;
using System.Security.Permissions;
// Delegate used for the compiled template
public delegate void RenderMethod(HtmlTextWriter output, Control container);
public delegate Control BuildMethod();
// Defines the properties, methods, and events that are shared by all server
// controls in the Web Forms page framework.
[
Bindable(true),
DefaultProperty("ID"),
DesignerCategory("Code"),
Designer("System.Web.UI.Design.ControlDesigner, " + AssemblyRef.SystemDesign),
DesignerSerializer("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, " + AssemblyRef.MicrosoftVisualStudioWeb, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + AssemblyRef.SystemDesign),
Themeable(false),
ToolboxItemFilter("System.Web.UI", ToolboxItemFilterType.Require),
ToolboxItemAttribute("System.Web.UI.Design.WebControlToolboxItem, " + AssemblyRef.SystemDesign)
]
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public class Control : IComponent, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor {
internal static readonly object EventDataBinding = new object();
internal static readonly object EventInit = new object();
internal static readonly object EventLoad = new object();
internal static readonly object EventUnload = new object();
internal static readonly object EventPreRender = new object();
private static readonly object EventDisposed = new object();
internal const bool EnableViewStateDefault = true;
internal const char ID_SEPARATOR = '$';
private const char ID_RENDER_SEPARATOR = '_';
internal const char LEGACY_ID_SEPARATOR = ':';
private string _id;
// allows us to reuse the id variable to store a calculated id w/o polluting the public getter
private string _cachedUniqueID;
private Control _parent;
// fields related to being a container
private ControlState _controlState;
private StateBag _viewState;
// The naming container that this control leaves in. Note that even if
// this ctrl is a naming container, it will not point to itself, but to
// the naming container that contains it.
private Control _namingContainer;
internal Page _page;
private OccasionalFields _occasionalFields;
private TemplateControl _templateControl;
// The virtual directory of the Page or UserControl that hosts this control.
private VirtualPath _templateSourceVirtualDirectory;
internal ControlAdapter _adapter;
// const masks into the BitVector32
private const int idNotCalculated = 0x00000001;
private const int marked = 0x00000002;
private const int disableViewState = 0x00000004;
private const int controlsCreated = 0x00000008;
private const int invisible = 0x00000010;
private const int visibleDirty = 0x00000020;
private const int idNotRequired = 0x00000040;
private const int isNamingContainer = 0x00000080;
private const int creatingControls = 0x00000100;
private const int notVisibleOnPage = 0x00000200;
private const int themeApplied = 0x00000400;
private const int mustRenderID = 0x00000800;
private const int disableTheming = 0x00001000;
private const int enableThemingSet = 0x00002000;
private const int styleSheetApplied = 0x00004000;
private const int controlAdapterResolved = 0x00008000;
private const int designMode = 0x00010000;
private const int designModeChecked = 0x00020000;
private const int disableChildControlState = 0x00040000;
internal const int isWebControlDisabled = 0x00080000;
private const int controlStateApplied = 0x00100000;
private const int useGeneratedID = 0x00200000;
#pragma warning disable 0649
internal SimpleBitVector32 flags;
#pragma warning restore 0649
private const string automaticIDPrefix = "ctl";
private const string automaticLegacyIDPrefix = "_ctl";
private const int automaticIDCount = 128;
private static readonly string[] automaticIDs = new string [automaticIDCount] {
"ctl00", "ctl01", "ctl02", "ctl03", "ctl04", "ctl05", "ctl06",
"ctl07", "ctl08", "ctl09", "ctl10", "ctl11", "ctl12", "ctl13",
"ctl14", "ctl15", "ctl16", "ctl17", "ctl18", "ctl19", "ctl20",
"ctl21", "ctl22", "ctl23", "ctl24", "ctl25", "ctl26", "ctl27",
"ctl28", "ctl29", "ctl30", "ctl31", "ctl32", "ctl33", "ctl34",
"ctl35", "ctl36", "ctl37", "ctl38", "ctl39", "ctl40", "ctl41",
"ctl42", "ctl43", "ctl44", "ctl45", "ctl46", "ctl47", "ctl48",
"ctl49", "ctl50", "ctl51", "ctl52", "ctl53", "ctl54", "ctl55",
"ctl56", "ctl57", "ctl58", "ctl59", "ctl60", "ctl61", "ctl62",
"ctl63", "ctl64", "ctl65", "ctl66", "ctl67", "ctl68", "ctl69",
"ctl70", "ctl71", "ctl72", "ctl73", "ctl74", "ctl75", "ctl76",
"ctl77", "ctl78", "ctl79", "ctl80", "ctl81", "ctl82", "ctl83",
"ctl84", "ctl85", "ctl86", "ctl87", "ctl88", "ctl89", "ctl90",
"ctl91", "ctl92", "ctl93", "ctl94", "ctl95", "ctl96", "ctl97",
"ctl98", "ctl99",
"ctl100", "ctl101", "ctl102", "ctl103", "ctl104", "ctl105", "ctl106",
"ctl107", "ctl108", "ctl109", "ctl110", "ctl111", "ctl112", "ctl113",
"ctl114", "ctl115", "ctl116", "ctl117", "ctl118", "ctl119", "ctl120",
"ctl121", "ctl122", "ctl123", "ctl124", "ctl125", "ctl126", "ctl127"
};
///
/// Initializes a new instance of the class.
///
public Control() {
if (this is INamingContainer)
flags.Set(isNamingContainer);
}
///
/// Indicates the control identifier generated by the ASP.NET framework. This
/// property is read-only.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_ClientID)
]
public virtual string ClientID {
// This property is required to render a unique client-friendly id.
get {
// Ensure that ID is set. The assumption being made is that the caller
// is likely to use the client ID in script, and to support that the
// control should render out an ID attribute
EnsureID();
string uniqueID = UniqueID;
if(uniqueID != null && uniqueID.IndexOf(IdSeparator) >= 0) {
return uniqueID.Replace(IdSeparator, ID_RENDER_SEPARATOR);
}
return uniqueID;
}
}
protected char ClientIDSeparator {
get {
return ID_RENDER_SEPARATOR;
}
}
///
/// [To be supplied.]
///
[
WebSysDescription(SR.Control_OnDisposed)
]
public event EventHandler Disposed {
add {
Events.AddHandler(EventDisposed, value);
}
remove {
Events.RemoveHandler(EventDisposed, value);
}
}
///
/// Gets the object of the current Web request. If
/// the control's context is , this will be the context of the
/// control's parent, unless the parent control's context is .
/// If this is the case, this will be equal to the HttpContext property.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
protected internal virtual HttpContext Context {
// Request context containing the intrinsics
get {
Page page = Page;
if(page != null) {
return page.Context;
}
return HttpContext.Current;
}
}
protected virtual ControlAdapter ResolveAdapter() {
if(flags[controlAdapterResolved]) {
return _adapter;
}
if (DesignMode) {
flags.Set(controlAdapterResolved);
return null;
}
HttpContext context = Context;
if (context != null) {
_adapter = context.Request.Browser.GetAdapter(this);
}
flags.Set(controlAdapterResolved);
return _adapter;
}
///
/// Indicates the list of event handler delegates for the control. This property
/// is read-only.
///
protected ControlAdapter Adapter {
get {
if(flags[controlAdapterResolved]) {
return _adapter;
}
_adapter = ResolveAdapter();
flags.Set(controlAdapterResolved);
return _adapter;
}
}
///
/// Indicates whether a control is being used in the context of a design surface.
///
protected internal bool DesignMode {
get {
if(!flags[designModeChecked]) {
Page page = Page;
if(page != null ) {
if(page.GetDesignModeInternal()) {
flags.Set(designMode);
}
else {
flags.Clear(designMode);
}
}
else {
if(Site != null) {
if(Site.DesignMode) {
flags.Set(designMode);
}
else {
flags.Clear(designMode);
}
}
else if (Parent != null) {
if(Parent.DesignMode) {
flags.Set(designMode);
}
// VSWhidbey 535747: If Page, Site and Parent are all null, do not change the
// designMode flag since it might had been previously set by the controlBuilder.
// This does not affect runtime since designMode is by-default false.
/*
else {
flags.Clear(designMode);
}
*/
}
}
flags.Set(designModeChecked);
}
return flags[designMode];
}
}
// Helper function to call validateEvent.
internal void ValidateEvent(string uniqueID) {
ValidateEvent(uniqueID, String.Empty);
}
// Helper function to call validateEvent.
internal void ValidateEvent(string uniqueID, string eventArgument) {
if (Page != null && SupportsEventValidation) {
Page.ClientScript.ValidateEvent(uniqueID, eventArgument);
}
}
// Indicates whether the control supports event validation
// By default, all web controls in System.Web assembly supports it but not custom controls.
private bool SupportsEventValidation {
get {
return SupportsEventValidationAttribute.SupportsEventValidation(this.GetType());
}
}
///
/// Indicates the list of event handler delegates for the control. This property
/// is read-only.
///
protected EventHandlerList Events {
get {
EnsureOccasionalFields();
if(_occasionalFields.Events == null) {
_occasionalFields.Events = new EventHandlerList();
}
return _occasionalFields.Events;
}
}
protected bool HasEvents() {
return ((_occasionalFields != null) && (_occasionalFields.Events != null));
}
///
/// Gets or sets the identifier for the control. Setting the
/// property on a control allows programmatic access to the control's properties. If
/// this property is not specified on a control, either declaratively or
/// programmatically, then you cannot write event handlers and the like for the control.
///
[
ParenthesizePropertyName(true),
MergableProperty(false),
Filterable(false),
Themeable(false),
WebSysDescription(SR.Control_ID)
]
public virtual string ID {
get {
if (!flags[idNotCalculated] && !flags[mustRenderID]) {
return null;
}
return _id;
}
set {
// allow the id to be unset
if (value != null && value.Length == 0)
value = null;
string oldID = _id;
_id = value;
ClearCachedUniqueIDRecursive();
flags.Set(idNotCalculated);
flags.Clear(useGeneratedID);
// Update the ID in the naming container
if ((_namingContainer != null) && (oldID != null)) {
_namingContainer.DirtyNameTable();
}
}
}
///
/// Gets and sets a value indicating whether theme is enabled.
///
[
Browsable(false),
DefaultValue(true),
Themeable(false),
WebCategory("Behavior"),
WebSysDescription(SR.Control_EnableTheming)
]
public virtual bool EnableTheming {
get {
if (flags[enableThemingSet]) {
return !flags[disableTheming];
}
if (Parent != null) {
return Parent.EnableTheming;
}
return !flags[disableTheming];
}
set {
if ((_controlState >= ControlState.FrameworkInitialized) && !DesignMode) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePreInitOrAddToControls, "EnableTheming"));
}
if(!value) {
flags.Set(disableTheming);
}
else {
flags.Clear(disableTheming);
}
flags.Set(enableThemingSet);
}
}
// Serialzie the value if it's set explicitely.
internal bool ShouldSerializeEnableTheming() {
return flags[enableThemingSet];;
}
internal bool IsBindingContainer {
get {
return this is INamingContainer && !(this is INonBindingContainer);
}
}
protected internal bool IsChildControlStateCleared {
get {
return flags[disableChildControlState];
}
}
///
/// Gets and sets the skinID of the control.
///
[
Browsable(false),
DefaultValue(""),
Filterable(false),
WebCategory("Behavior"),
WebSysDescription(SR.Control_SkinId),
]
public virtual string SkinID {
get {
if(_occasionalFields != null) {
return _occasionalFields.SkinId == null ? String.Empty : _occasionalFields.SkinId;
}
return String.Empty;
}
set {
if (!DesignMode) {
if (flags[styleSheetApplied]) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforeStyleSheetApplied, "SkinId"));
}
if (_controlState >= ControlState.FrameworkInitialized) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePreInitOrAddToControls, "SkinId"));
}
}
EnsureOccasionalFields();
_occasionalFields.SkinId = value;
}
}
private ControlRareFields RareFieldsEnsured {
get {
EnsureOccasionalFields();
ControlRareFields rareFields = _occasionalFields.RareFields;
if(rareFields == null) {
rareFields = new ControlRareFields();
_occasionalFields.RareFields = rareFields;
}
return rareFields;
}
}
private ControlRareFields RareFields {
get {
if(_occasionalFields != null) {
return _occasionalFields.RareFields;
}
return null;
}
}
private void EnsureOccasionalFields() {
if(_occasionalFields == null) {
_occasionalFields = new OccasionalFields();
}
}
///
///
/// Gets or sets a value indicating whether the control should maintain its view
/// state, and the view state of any child control in contains, when the current
/// page request ends.
///
///
[
DefaultValue(EnableViewStateDefault),
Themeable(false),
WebCategory("Behavior"),
WebSysDescription(SR.Control_MaintainState)
]
public virtual bool EnableViewState {
get {
return !flags[disableViewState];
}
set {
SetEnableViewStateInternal(value);
}
}
internal void SetEnableViewStateInternal(bool value) {
if (!value)
flags.Set(disableViewState);
else
flags.Clear(disableViewState);
}
///
/// Gets a value indicating whether the control is maintaining its view
/// state, when the current page request ends by looking at its own EnableViewState
/// value, and the value for all its parents.
///
protected internal bool IsViewStateEnabled {
get {
Control current = this;
while (current != null) {
if (current.EnableViewState == false) {
return false;
}
current = current.Parent;
}
return true;
}
}
///
/// Gets the reference to the current control's naming container.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_NamingContainer)
]
public virtual Control NamingContainer {
get {
if (_namingContainer == null) {
if (Parent != null) {
// Search for the closest naming container in the tree
if (Parent.flags[isNamingContainer])
_namingContainer = Parent;
else
_namingContainer = Parent.NamingContainer;
}
}
return _namingContainer;
}
}
///
///
/// Returns the databinding container of this control. In most cases,
/// this is the same as the NamingContainer. But when using LoadTemplate(),
/// we get into a situation where that is not the case (ASURT 94138)
/// The behavior is different than V1 that Usercontrol.BindingContainer is no
/// longer the UserControl but the control contains it. The behavior is consistent
/// with LoadTemplate() case.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never)
]
public Control BindingContainer {
get {
Control bindingContainer = NamingContainer;
while (bindingContainer is INonBindingContainer) {
bindingContainer = bindingContainer.BindingContainer;
}
return bindingContainer;
}
}
///
///
/// VSWhidbey 80467: Need to adapt id separator.
///
protected char IdSeparator {
get {
if (Page != null) {
return Page.IdSeparator;
}
return IdSeparatorFromConfig;
}
}
// VSWhidbey 475945: Use the old id separator if configured
internal char IdSeparatorFromConfig {
get {
return ((EnableLegacyRendering) ? LEGACY_ID_SEPARATOR : ID_SEPARATOR);
}
}
// VSWhidbey 244374: Allow controls to opt into loading view state by ID instead of index (perf hit)
protected bool LoadViewStateByID {
get {
return ViewStateModeByIdAttribute.IsEnabled(GetType());
}
}
///
/// Gets the object that contains the
/// current control.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Page)
]
public virtual Page Page {
get {
if (_page == null) {
if (Parent != null) {
_page = Parent.Page;
}
}
return _page;
}
set {
if (OwnerControl != null) {
throw new InvalidOperationException();
}
// This is necessary because we need to set the page in generated
// code before controls are added to the tree (ASURT 75330)
Debug.Assert(_page == null);
Debug.Assert(Parent == null || Parent.Page == null);
_page = value;
}
}
// VSWhidbey 244999
internal virtual bool IsReloadable {
get {
return false;
}
}
// DevDiv 33149, 43258: A backward compat. switch for Everett rendering
internal bool EnableLegacyRendering {
get {
Page page = Page;
if (page != null) {
return (page.XhtmlConformanceMode == XhtmlConformanceMode.Legacy);
}
else if (DesignMode || Adapter != null) {
return false;
}
else {
return (GetXhtmlConformanceSection().Mode == XhtmlConformanceMode.Legacy);
}
}
}
internal XhtmlConformanceSection GetXhtmlConformanceSection() {
HttpContext context = Context;
XhtmlConformanceSection xhtmlConformanceSection;
if (context != null) {
// if context is available, use the most efficient way to get the section
xhtmlConformanceSection = RuntimeConfig.GetConfig(context).XhtmlConformance;
}
else {
xhtmlConformanceSection = RuntimeConfig.GetConfig().XhtmlConformance;
}
Debug.Assert(xhtmlConformanceSection != null);
return xhtmlConformanceSection;
}
#if ORCAS
///
/// Gets the object that
/// paginates the current control.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Pager)
]
public virtual ContentPager ContentPager {
get {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.ContentPager == null) {
if (Parent != null) {
rareFields.ContentPager = Parent.ContentPager;
}
}
return rareFields.ContentPager;
}
set {
RareFieldsEnsured.ContentPager = value;
}
}
#endif
///
/// Gets the reference to the
/// that hosts the control.
///
internal virtual TemplateControl GetTemplateControl() {
if(_templateControl == null) {
if (Parent != null) {
_templateControl = Parent.GetTemplateControl();
}
}
return _templateControl;
}
///
/// Gets the reference to the
/// that hosts the control.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_TemplateControl)
]
public TemplateControl TemplateControl {
get {
return GetTemplateControl();
}
[EditorBrowsable(EditorBrowsableState.Never)]
set {
// This setter is necessary so that controls inside templates are based on
// hosting pages not where the templates are used.
_templateControl = value;
}
}
/*
* Determine whether this control is a descendent of the passed in control
*/
internal bool IsDescendentOf(Control ancestor) {
Control current = this;
while (current != ancestor && current.Parent != null) {
current = current.Parent;
}
return (current == ancestor);
}
///
/// Gets the current control's parent control in the UI hierarchy.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Parent)
]
public virtual Control Parent {
get {
return _parent;
}
}
internal bool IsParentedToUpdatePanel {
get {
Control parent = Parent;
while (parent != null) {
if (parent is IUpdatePanel) {
return true;
}
parent = parent.Parent;
}
return false;
}
}
///
/// Gets the virtual directory of the Page or UserControl that contains this control.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_TemplateSourceDirectory)
]
public virtual string TemplateSourceDirectory {
get {
if (TemplateControlVirtualDirectory == null)
return String.Empty;
return TemplateControlVirtualDirectory.VirtualPathStringNoTrailingSlash;
}
}
///
/// Gets the virtual directory of the Page or UserControl that contains this control.
/// Unlike TemplateSourceDirectory, this returns an app relative path (e.g. "~/sub")
///
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Advanced),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_TemplateSourceDirectory)
]
public string AppRelativeTemplateSourceDirectory {
get {
return VirtualPath.GetAppRelativeVirtualPathStringOrEmpty(TemplateControlVirtualDirectory);
}
[EditorBrowsable(EditorBrowsableState.Never)]
set {
// This setter is necessary so that skins are based on hosting skin file.
this.TemplateControlVirtualDirectory = VirtualPath.CreateNonRelativeAllowNull(value);
}
}
internal VirtualPath TemplateControlVirtualDirectory {
get {
if (_templateSourceVirtualDirectory != null)
return _templateSourceVirtualDirectory;
TemplateControl control = TemplateControl;
if (control == null) {
HttpContext context = Context;
if (context != null) {
_templateSourceVirtualDirectory = context.Request.CurrentExecutionFilePathObject.Parent;
}
return _templateSourceVirtualDirectory;
}
// Prevent recursion if this is the TemplateControl
if (control != this) {
_templateSourceVirtualDirectory = control.TemplateControlVirtualDirectory;
}
return _templateSourceVirtualDirectory;
}
set {
// This setter is necessary so that skins are based on hosting skin file.
_templateSourceVirtualDirectory = value;
}
}
internal ControlState ControlState {
get { return _controlState; }
set { _controlState = value; }
}
///
/// Indicates the site information for the control.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Advanced),
WebSysDescription(SR.Control_Site)
]
public ISite Site {
get {
if (OwnerControl != null) {
return OwnerControl.Site;
}
if (RareFields != null) {
return RareFields.Site;
}
return null;
}
set {
if (OwnerControl != null) {
throw new InvalidOperationException(SR.GetString(SR.Substitution_SiteNotAllowed));
}
RareFieldsEnsured.Site = value;
flags.Clear(designModeChecked);
}
}
///
///
/// Gets or sets a value that indicates whether a control should be rendered on
/// the page.
///
///
[
Bindable(true),
DefaultValue(true),
WebCategory("Behavior"),
WebSysDescription(SR.Control_Visible)
]
public virtual bool Visible {
get {
if (flags[invisible])
return false;
#if ORCAS
if (NotVisibleOnPage)
return false;
#endif
else if ((_parent != null) && !DesignMode)
return _parent.Visible;
else
return true;
}
set {
if (flags[marked]) {
bool visible = !flags[invisible];
if (visible != value) {
flags.Set(visibleDirty);
}
}
if(!value) {
flags.Set(invisible);
}
else {
flags.Clear(invisible);
}
}
}
#if ORCAS
internal bool ExplicitlyInvisible {
get {
return flags[invisible];
}
}
#endif
///
/// Do not remove or change the signature. It is called via reflection.
/// This allows for correct serialization, since Visible is implemented as a
/// recursive property.
///
private void ResetVisible() {
Visible = true;
}
///
/// Do not remove or change the signature. It is called via reflection.
/// This allows for correct serialization, since Visible is implemented as a
/// recursive property.
///
private bool ShouldSerializeVisible() {
return flags[invisible];
}
///
/// Gets the unique, hierarchically-qualified identifier for
/// a control. This is different from the ID property, in that the fully-qualified
/// identifier includes the identifier for the control's naming container.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_UniqueID)
]
public virtual string UniqueID {
get {
if (_cachedUniqueID != null) {
return _cachedUniqueID;
}
Control namingContainer = NamingContainer;
if (namingContainer != null) {
// if the ID is null at this point, we need to have one created and the control added to the
// naming container.
if (_id == null) {
GenerateAutomaticID();
}
if (Page == namingContainer) {
_cachedUniqueID = _id;
}
else {
string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();
if (uniqueIDPrefix.Length == 0) {
// In this case, it is probably a naming container that is not sited, so we don't want to cache it
return _id;
}
else {
_cachedUniqueID = uniqueIDPrefix + _id;
}
}
return _cachedUniqueID;
}
else {
// no naming container
return _id;
}
}
}
#if SHIPPINGADAPTERS
// Used by adapters in delegating rendering (e.g., a Button for a LinkButton for scriptless devices).
// The UniqueID of the new control has to be set to match the UniqueID of the original.
internal void SetUniqueID(string val) {
_cachedUniqueID = val;
}
#endif
///
/// Occurs when the control binds to a data source. Notifies the control to perform any data binding during this event.
///
[
WebCategory("Data"),
WebSysDescription(SR.Control_OnDataBind)
]
public event EventHandler DataBinding {
add {
Events.AddHandler(EventDataBinding, value);
}
remove {
Events.RemoveHandler(EventDataBinding, value);
}
}
///
/// Occurs when the control is initialized, the first step in the page lifecycle. Controls should
/// perform any initialization steps that are required to create and set up an
/// instantiation.
///
[
WebSysDescription(SR.Control_OnInit)
]
public event EventHandler Init {
add {
Events.AddHandler(EventInit, value);
}
remove {
Events.RemoveHandler(EventInit, value);
}
}
///
/// Occurs when the control is loaded to the object. Notifies the control to perform any steps that
/// need to occur on each page request.
///
[
WebSysDescription(SR.Control_OnLoad)
]
public event EventHandler Load {
add {
Events.AddHandler(EventLoad, value);
}
remove {
Events.RemoveHandler(EventLoad, value);
}
}
///
/// Occurs when the control is about to render. Controls
/// should perform any pre-rendering steps necessary before saving view state and
/// rendering content to the object.
///
[
WebSysDescription(SR.Control_OnPreRender)
]
public event EventHandler PreRender {
add {
Events.AddHandler(EventPreRender, value);
}
remove {
Events.RemoveHandler(EventPreRender, value);
}
}
///
/// Occurs when the control is unloaded from memory. Controls should perform any
/// final cleanup before this instance of it is
///
[
WebSysDescription(SR.Control_OnUnload)
]
public event EventHandler Unload {
add {
Events.AddHandler(EventUnload, value);
}
remove {
Events.RemoveHandler(EventUnload, value);
}
}
///
/// Apply stylesheet skin on the control.
///
[
EditorBrowsable(EditorBrowsableState.Advanced),
]
public virtual void ApplyStyleSheetSkin(Page page) {
// Nothing to do if the control is not in a Page.
if (page == null) {
return;
}
// Only apply stylesheet if not already applied.
if (flags[styleSheetApplied]) {
throw new InvalidOperationException(SR.GetString(SR.StyleSheetAreadyAppliedOnControl));
}
if (page.ApplyControlStyleSheet(this)) {
flags.Set(styleSheetApplied);
}
}
///
/// Apply theme on the control.
///
private void ApplySkin(Page page) {
if (page == null) {
throw new ArgumentNullException("page");
}
if (flags[themeApplied]) {
return;
}
if (ThemeableAttribute.IsTypeThemeable(this.GetType())) {
page.ApplyControlSkin(this);
flags.Set(themeApplied);
}
}
///
/// Raises the event. This
/// notifies a control to perform any data binding logic that is associated with it.
///
protected virtual void OnDataBinding(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventDataBinding] as EventHandler;
if(handler != null) {
handler(this, e);
}
}
}
///
/// Causes data binding to occur on the invoked control and all of its child
/// controls.
///
public virtual void DataBind() {
DataBind(true);
}
///
/// Causes the invoked controls' context to be pushed on the stack,
/// then conditionally call OnDataBinging on the invoked control, and databind all of its child
/// controls. A control would call this with false if it overrides DataBind without calling
/// Control.DataBind, but still wants to be an IDataItemContainer. FormView and DetailsView
/// are good examples of this.
///
protected virtual void DataBind(bool raiseOnDataBinding) {
bool inDataBind = false;
if (IsBindingContainer) {
bool foundDataItem;
object dataItem = DataBinder.GetDataItem(this, out foundDataItem);
if (foundDataItem && (Page != null)) {
Page.PushDataBindingContext(dataItem);
inDataBind = true;
}
}
try {
if (raiseOnDataBinding) {
// Do our own databinding
OnDataBinding(EventArgs.Empty);
}
// Do all of our children's databinding
DataBindChildren();
}
finally {
if (inDataBind) {
Page.PopDataBindingContext();
}
}
}
///
/// Causes data binding to occur on all of the child controls.
///
protected virtual void DataBindChildren() {
if (HasControls()) {
EnsureOccasionalFields();
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
try {
try {
int controlCount = _occasionalFields.Controls.Count;
for (int i=0; i < controlCount; i++)
_occasionalFields.Controls[i].DataBind();
}
finally {
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
}
catch {
throw;
}
}
}
internal void PreventAutoID() {
// controls that are also naming containers must always get an id
if (flags[isNamingContainer] == false) {
flags.Set(idNotRequired);
}
}
///
/// Notifies the control that an element, XML or HTML, was parsed, and adds it to
/// the control.
///
protected virtual void AddParsedSubObject(object obj) {
Control control = obj as Control;
if (control != null) {
Controls.Add(control);
}
}
private void UpdateNamingContainer(Control namingContainer) {
// Remove the cached uniqueID if the control already had a namingcontainer
// and the namingcontainer is changed.
if (_namingContainer != null && _namingContainer != namingContainer) {
ClearCachedUniqueIDRecursive();
}
_namingContainer = namingContainer;
}
private void ClearCachedUniqueIDRecursive() {
_cachedUniqueID = null;
if (_occasionalFields != null) {
_occasionalFields.UniqueIDPrefix = null;
if (_occasionalFields.Controls != null) {
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
_occasionalFields.Controls[i].ClearCachedUniqueIDRecursive();
}
}
}
}
protected void EnsureID() {
if (_namingContainer != null) {
if (_id == null) {
GenerateAutomaticID();
}
flags.Set(mustRenderID);
}
}
private void GenerateAutomaticID() {
Debug.Assert(_namingContainer != null);
Debug.Assert(_id == null);
// Remember that a generated ID is used for this control.
flags.Set(useGeneratedID);
// Calculate the automatic ID. For performance and memory reasons
// we look up a static table entry if possible
_namingContainer.EnsureOccasionalFields();
int idNo = _namingContainer._occasionalFields.NamedControlsID++;
if (EnableLegacyRendering) {
// VSWhidbey 517118
_id = automaticLegacyIDPrefix + idNo.ToString(NumberFormatInfo.InvariantInfo);
}
else {
if (idNo < automaticIDCount) {
_id = automaticIDs[idNo];
}
else {
_id = automaticIDPrefix + idNo.ToString(NumberFormatInfo.InvariantInfo);
}
}
_namingContainer.DirtyNameTable();
}
internal virtual string GetUniqueIDPrefix() {
EnsureOccasionalFields();
if (_occasionalFields.UniqueIDPrefix == null) {
string uniqueID = UniqueID;
if (!String.IsNullOrEmpty(uniqueID)) {
_occasionalFields.UniqueIDPrefix = uniqueID + IdSeparator;
}
else {
_occasionalFields.UniqueIDPrefix = String.Empty;
}
}
return _occasionalFields.UniqueIDPrefix;
}
///
/// Raises the event. This notifies the control to perform
/// any steps necessary for its creation on a page request.
///
protected internal virtual void OnInit(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventInit] as EventHandler;
if(handler != null) {
handler(this, e);
}
}
}
internal virtual void InitRecursive(Control namingContainer) {
ResolveAdapter();
if (_occasionalFields != null && _occasionalFields.Controls != null) {
if (flags[isNamingContainer]) {
namingContainer = this;
}
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
Control control = _occasionalFields.Controls[i];
// Propagate the page and namingContainer
control.UpdateNamingContainer(namingContainer);
if ((control._id == null) && (namingContainer != null) && !control.flags[idNotRequired]) {
control.GenerateAutomaticID();
}
control._page = Page;
control.InitRecursive(namingContainer);
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
// Only make the actual call if it hasn't already happened (ASURT 111303)
if (_controlState < ControlState.Initialized) {
_controlState = ControlState.ChildrenInitialized; // framework also initialized
if ((Page != null) && !DesignMode) {
if (Page.ContainsTheme && EnableTheming) {
ApplySkin(Page);
}
}
if (_adapter != null) {
_adapter.OnInit(EventArgs.Empty);
}
else {
OnInit(EventArgs.Empty);
}
_controlState = ControlState.Initialized;
}
// track all subsequent state changes
TrackViewState();
#if DEBUG
ControlInvariant();
#endif
}
#if DEBUG
///
/// This should be used to assert internal state about the control
///
internal void ControlInvariant() {
// If the control is initialized, the naming container and page should have been pushed in
if (_controlState >= ControlState.Initialized) {
if (DesignMode) {
// Top-level UserControls do not have a page or a naming container in the designer
// hence the special casing.
Debug.Assert((_namingContainer != null) || (this is Page) || (this is UserControl));
//
}
else {
if (!(this is Page)) {
Debug.Assert(_namingContainer != null);
}
Debug.Assert(Page != null);
}
}
// If naming container is set and the name table exists, the ID should exist in it.
if(_namingContainer != null &&
_namingContainer._occasionalFields != null &&
_namingContainer._occasionalFields.NamedControls != null &&
_id != null) {
Debug.Assert(_namingContainer._occasionalFields.NamedControls.Contains(_id));
}
}
// Collect some statistic about the number of controls with occasional and
// rare fields.
internal void GetRareFieldStatistics(ref int totalControls,
ref int withOccasionalFields, ref int withRareFields) {
totalControls++;
if (_occasionalFields != null) {
withOccasionalFields++;
if (_occasionalFields.RareFields != null)
withRareFields++;
// No children: we're done
if (_occasionalFields.Controls == null)
return;
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
Control control = _occasionalFields.Controls[i];
control.GetRareFieldStatistics(ref totalControls, ref withOccasionalFields,
ref withRareFields);
}
}
}
#endif
protected void ClearChildState() {
ClearChildControlState();
ClearChildViewState();
}
protected void ClearChildControlState() {
//VSWhidbey 242621 to be consistent with ClearChildViewState, ignore calls before and during Init
if (ControlState < ControlState.Initialized) {
return;
}
flags.Set(disableChildControlState);
if (Page != null) {
Page.RegisterRequiresClearChildControlState(this);
}
}
///
/// Deletes the view state information for all of the current control's child
/// controls.
///
protected void ClearChildViewState() {
if(_occasionalFields != null) {
_occasionalFields.ControlsViewState = null;
}
}
///
/// Indicates whether the current control's children have any saved view state
/// information. This property is read-only.
///
protected bool HasChildViewState {
get {
return ((_occasionalFields != null) &&
(_occasionalFields.ControlsViewState != null) &&
(_occasionalFields.ControlsViewState.Count > 0));
}
}
///
/// Sets initial focus on the control
///
public virtual void Focus() {
Page.SetFocus(this);
}
internal void LoadControlStateInternal(object savedStateObj) {
// Do not load the control state if it has been applied.
if (flags[controlStateApplied]) {
return;
}
flags.Set(controlStateApplied);
Pair savedState = (Pair)savedStateObj;
if (savedState == null) {
return;
}
Page page = Page;
if (page != null && !page.ShouldLoadControlState(this)) {
return;
}
// VSWhidbey160650: Only call LoadControlState with non null savedState
if (savedState.First != null) {
LoadControlState(savedState.First);
}
// VSWhidbey356804: Only call LoadAdapterControlState with non null savedState
if (_adapter == null || savedState.Second == null) {
return;
}
_adapter.LoadAdapterControlState(savedState.Second);
}
///
/// Load the control state, which is the essential state information needed even if view state is disabled.
///
protected internal virtual void LoadControlState(object savedState) {
}
///
/// Restores the view state information from a previous page
/// request that was saved by the Control.SavedState method.
///
protected virtual void LoadViewState(object savedState) {
if (savedState != null) {
ViewState.LoadViewState(savedState);
// Load values cached out of view state
object visible = ViewState["Visible"];
if (visible != null) {
if(!(bool)visible) {
flags.Set(invisible);
}
else {
flags.Clear(invisible);
}
flags.Set(visibleDirty);
}
}
}
internal void LoadViewStateRecursive(object savedState) {
// nothing to do if we have no state
if (savedState == null || flags[disableViewState])
return;
if (Page != null && Page.IsPostBack) {
object controlState = null;
object adapterState = null;
ArrayList childState = null;
Pair allSavedState = savedState as Pair;
if (allSavedState != null) {
controlState = allSavedState.First;
childState = (ArrayList)allSavedState.Second;
}
else {
Debug.Assert(savedState is Triplet);
Triplet t = (Triplet)savedState;
controlState = t.First;
adapterState = t.Second;
childState = (ArrayList)t.Third;
}
try {
if ((adapterState != null) && (_adapter != null)) {
_adapter.LoadAdapterViewState(adapterState);
}
if (controlState != null) {
LoadViewState(controlState);
}
if (childState != null) {
if (LoadViewStateByID) {
LoadChildViewStateByID(childState);
}
else {
LoadChildViewStateByIndex(childState);
}
}
}
catch (InvalidCastException) {
// catch all viewstate loading problems with casts. They are most likely changed control trees.
throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
}
catch (IndexOutOfRangeException) {
// catch all viewstate loading problems with indeces. They are most likely changed control trees.
throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
}
}
_controlState = ControlState.ViewStateLoaded;
}
internal void LoadChildViewStateByID(ArrayList childState) {
int childStateCount = childState.Count;
for (int i = 0; i < childStateCount; i += 2) {
// first element is index or ID of control with state and the
// next element is state of the control
string controlId = (string)childState[i];
object state = childState[i + 1];
Control childControl = FindControl(controlId);
if (childControl != null) {
childControl.LoadViewStateRecursive(state);
}
else {
// couldn't find a control for this state blob, save it for later
EnsureOccasionalFields();
if (_occasionalFields.ControlsViewState == null) {
_occasionalFields.ControlsViewState = new Hashtable();
}
_occasionalFields.ControlsViewState[controlId] = state;
}
}
}
internal void LoadChildViewStateByIndex(ArrayList childState) {
ControlCollection ctrlColl = Controls;
int ctrlCount = ctrlColl.Count;
int childStateCount = childState.Count;
for (int i = 0; i < childStateCount; i += 2) {
// first element is index of control with state and the
// next element is state of the control
int controlIndex = (int)childState[i];
object state = childState[i + 1];
if (controlIndex < ctrlCount) {
// we have a control for this state blob
ctrlColl[controlIndex].LoadViewStateRecursive(state);
}
else {
// couldn't find a control for this state blob, save it for later
EnsureOccasionalFields();
if (_occasionalFields.ControlsViewState == null) {
_occasionalFields.ControlsViewState = new Hashtable();
}
_occasionalFields.ControlsViewState[controlIndex] = state;
}
}
}
///
/// Figure out if a path is physical or virtual. This is useful because a number of our controls
/// accept either type of path for the same attribute.
///
internal void ResolvePhysicalOrVirtualPath(string path, out VirtualPath virtualPath, out string physicalPath) {
if (System.Web.Util.UrlPath.IsAbsolutePhysicalPath(path)) {
physicalPath = path;
virtualPath = null;
}
else {
physicalPath = null;
// It could be relative, so resolve it
virtualPath = TemplateControlVirtualDirectory.Combine(VirtualPath.Create(path));
}
}
///
///
/// This function takes a virtual path, that is a relative or root relative URL without a protocol.
/// It returns the mapped physcial file name relative to the template source. It throws an exception if
/// there is insufficient security access to read or investigate the mapped result. This should be used
/// by controls that can read files and live in fully trusted DLLs such as System.Web.dll to prevent
/// security issues. The exception thrown does not give away information about the mapping. For absolute
/// physical paths, this function checks permission
///
///
protected internal string MapPathSecure(string virtualPath) {
if (String.IsNullOrEmpty(virtualPath)) {
throw new ArgumentNullException("virtualPath", SR.GetString(SR.VirtualPath_Length_Zero));
}
string physicalPath;
VirtualPath virtualPathObject;
ResolvePhysicalOrVirtualPath(virtualPath, out virtualPathObject, out physicalPath);
if (physicalPath == null) {
physicalPath = virtualPathObject.MapPathInternal(TemplateControlVirtualDirectory,
true /*allowCrossAppMapping*/);
}
// Security check
HttpRuntime.CheckFilePermission(physicalPath);
return physicalPath;
}
///
///
/// This function takes a virtual path, that is a relative or root relative URL without a protocol.
/// It can also take a physical path, either local (c:\) or UNC.
/// It returns a stream used to read to contents of the file. It throws an exception if
/// there is insufficient security access to read or investigate the mapped result. This should be used
/// by controls that can read files and live in fully trusted DLLs such as System.Web.dll to prevent
/// security issues. The exception thrown does not give away information about the mapping. For absolute
/// physical paths, this function checks permission
///
///
protected internal Stream OpenFile(string path) {
string physicalPath = null;
VirtualFile vfile = null;
// Need to Trim it since MapPath no longer allows trailing space (VSWhidbey 441210)
path = path.Trim();
if (UrlPath.IsAbsolutePhysicalPath(path)) {
// Absolute physical path
physicalPath = path;
}
else {
vfile = HostingEnvironment.VirtualPathProvider.GetFile(path);
MapPathBasedVirtualFile mapPathVFile = vfile as MapPathBasedVirtualFile;
if (mapPathVFile != null) {
physicalPath = mapPathVFile.PhysicalPath;
}
}
// If we got a physical path, make sure the user has access to it
if (physicalPath != null) {
HttpRuntime.CheckFilePermission(physicalPath);
}
if (vfile != null) {
return vfile.Open();
}
else {
return new FileStream(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
}
///
/// Open a stream from either a virtual or physical path, and if possible get a CacheDependency
/// for the resulting Stream.
///
internal Stream OpenFileAndGetDependency(VirtualPath virtualPath, string physicalPath, out CacheDependency dependency) {
// Only one of the paths should be non-null
Debug.Assert((virtualPath == null) != (physicalPath == null));
// If we got a virtual path, and we're using the default VPP, call MapPath
if (physicalPath == null && HostingEnvironment.UsingMapPathBasedVirtualPathProvider) {
physicalPath = virtualPath.MapPathInternal(TemplateControlVirtualDirectory,
true /*allowCrossAppMapping*/);
}
Stream stream;
if (physicalPath != null) {
// Security check
HttpRuntime.CheckFilePermission(physicalPath);
// Work directly with the physical file, bypassing the VPP
stream = new FileStream(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
dependency = new CacheDependency(0, physicalPath);
}
else {
// It's non file system based, so go though the VirtualPathProvider
stream = virtualPath.OpenFile();
dependency = VirtualPathProvider.GetCacheDependency(virtualPath);
}
return stream;
}
///
/// Raises the
/// event. This notifies the control that it should perform any work that needs to
/// occur for each page request.
///
protected internal virtual void OnLoad(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventLoad] as EventHandler;
if(handler != null) {
handler(this, e);
}
}
}
internal virtual void LoadRecursive() {
// Only make the actual call if it hasn't already happened (ASURT 111303)
if (_controlState < ControlState.Loaded) {
if(_adapter != null) {
_adapter.OnLoad(EventArgs.Empty);
}
else {
OnLoad(EventArgs.Empty);
}
}
// Call Load on all our children
if (_occasionalFields != null && _occasionalFields.Controls != null) {
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
_occasionalFields.Controls[i].LoadRecursive();
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
if (_controlState < ControlState.Loaded)
_controlState = ControlState.Loaded;
}
///
/// Raises the event. This method uses event arguments
/// to pass the event data to the control.
///
protected internal virtual void OnPreRender(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventPreRender] as EventHandler;
if (handler != null) {
handler(this, e);
}
}
}
internal virtual void PreRenderRecursiveInternal() {
// Call Visible property and cache value in !flags[invisible] to allow Visible to be overridden.
// This avoids unnecessary virtual property calls in SaveViewState and Render.
bool visible = Visible;
if(!visible) {
flags.Set(invisible);
}
else {
flags.Clear(invisible);
EnsureChildControls();
if(_adapter != null) {
_adapter.OnPreRender(EventArgs.Empty);
}
else {
OnPreRender(EventArgs.Empty);
}
if (_occasionalFields != null && _occasionalFields.Controls != null) {
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i=0; i < controlCount; i++) {
_occasionalFields.Controls[i].PreRenderRecursiveInternal();
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
}
_controlState = ControlState.PreRendered;
}
internal int EstimateStateSize(object state) {
if(state == null) {
return 0;
}
return Util.SerializeWithAssert(new ObjectStateFormatter(), state).Length;
}
/*
* Walk the tree and fill in profile information
*/
///
///
/// Gathers information about the control and delivers it to the
/// property to be displayed when tracing is enabled for the page.
///
protected void BuildProfileTree(string parentId, bool calcViewState) {
// estimate the viewstate size.
calcViewState = calcViewState && (!flags[disableViewState]);
int viewstatesize;
if (calcViewState)
viewstatesize = EstimateStateSize(SaveViewState());
else
viewstatesize = 0;
int controlstatesize = 0;
if(Page != null && Page._registeredControlsRequiringControlState != null && Page._registeredControlsRequiringControlState.Contains(this)) {
controlstatesize = EstimateStateSize(SaveControlStateInternal());
}
// give it all to the profiler
Page.Trace.AddNewControl(UniqueID, parentId, this.GetType().FullName, viewstatesize, controlstatesize);
if (_occasionalFields != null && _occasionalFields.Controls != null) {
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
_occasionalFields.Controls[i].BuildProfileTree(UniqueID, calcViewState);
}
}
}
internal object SaveControlStateInternal() {
object controlState = SaveControlState();
object adapterControlState = null;
if (_adapter != null) {
adapterControlState = _adapter.SaveAdapterControlState();
}
if (controlState != null || adapterControlState != null) {
return new Pair(controlState, adapterControlState);
}
return null;
}
///
/// Save the control state, which is the essential state information needed even if view state is disabled.
///
protected internal virtual object SaveControlState() {
return null;
}
// Save modified state the control would like restored on the postback.
// Return null if there is no state to save.
///
///
/// Saves view state for use with a later
/// request.
///
///
protected virtual object SaveViewState() {
// Save values cached out of view state
if (flags[visibleDirty]) {
ViewState["Visible"] = !flags[invisible];
}
if (_viewState != null)
return _viewState.SaveViewState();
return null;
}
// Answer any state this control or its descendants want to save on freeze.
// The format for saving is Triplet(myState, ArrayList childIDs, ArrayList childStates),
// where myState or childStates and childIDs may be null.
internal object SaveViewStateRecursive() {
if (flags[disableViewState])
return null;
object adapterState = null;
if (_adapter != null) {
adapterState = _adapter.SaveAdapterViewState();
}
object controlSavedState = SaveViewState();
ArrayList childStates = null;
if (HasControls()) {
ControlCollection occasionalFieldControls = _occasionalFields.Controls;
int occasionalFieldControlCount = occasionalFieldControls.Count;
bool useId = LoadViewStateByID;
for (int i = 0; i < occasionalFieldControlCount; i++) {
Control child = occasionalFieldControls[i];
object childState = child.SaveViewStateRecursive();
if (childState != null) {
if (childStates == null) {
childStates = new ArrayList(occasionalFieldControlCount);
}
if (useId) {
child.EnsureID();
childStates.Add(child.ID);
}
else {
childStates.Add(i);
}
childStates.Add(childState);
}
}
}
if (_adapter != null) {
if ((controlSavedState != null) || (adapterState != null) || (childStates != null)) {
return new Triplet(controlSavedState, adapterState, childStates);
}
}
else {
if ((controlSavedState != null) || (childStates != null)) {
return new Pair(controlSavedState, childStates);
}
}
return null;
}
///
/// Outputs control content to a provided HTMLTextWriter
/// output stream.
///
protected internal virtual void Render(HtmlTextWriter writer) {
RenderChildren(writer);
}
internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children) {
// If we have a delegate, use it for the rendering.
// This happens when there is some ASP code. See also Whidbey 33012.
if(RareFields != null && RareFields.RenderMethod != null ) {
writer.BeginRender();
RareFields.RenderMethod(writer, this);
writer.EndRender();
return;
}
if (children != null) {
foreach (Control child in children) {
child.RenderControl(writer);
}
}
}
protected internal virtual void RenderChildren(HtmlTextWriter writer) {
ICollection children = (_occasionalFields == null) ? null : _occasionalFields.Controls;
RenderChildrenInternal(writer, children);
}
///
/// [To be supplied.]
///
public virtual void RenderControl(HtmlTextWriter writer) {
//use the Adapter property to ensure it is resolved
RenderControl(writer, Adapter);
}
///
/// Used for MobilePage implementation.
///
protected void RenderControl(HtmlTextWriter writer, ControlAdapter adapter) {
if (!flags[invisible] && !flags[notVisibleOnPage]) {
HttpContext context = (Page == null) ? null : Page._context;
if (context != null && context.TraceIsEnabled) {
int presize = context.Response.GetBufferedLength();
RenderControlInternal(writer, adapter);
int postsize = context.Response.GetBufferedLength();
context.Trace.AddControlSize(UniqueID, postsize - presize);
}
else {
RenderControlInternal(writer, adapter);
}
}
}
private void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) {
if (adapter != null) {
//
adapter.BeginRender(writer);
adapter.Render(writer);
adapter.EndRender(writer);
}
else {
Render(writer);
}
}
///
/// [To be supplied.]
///
protected internal virtual void OnUnload(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventUnload] as EventHandler;
if (handler != null) {
handler(this, e);
}
}
}
///
/// Enables a control to perform final cleanup.
///
public virtual void Dispose() {
IContainer container = null;
if (Site != null) {
container = (IContainer)Site.GetService(typeof(IContainer));
if (container != null) {
container.Remove(this);
EventHandler disp = Events[EventDisposed] as EventHandler;
if (disp != null)
disp(this, EventArgs.Empty);
}
}
if (_occasionalFields != null) {
_occasionalFields.Dispose();
//do not null out for backwards compat, VSWhidbey 475940
//_occasionalFields = null;
}
}
internal virtual void UnloadRecursive(bool dispose) {
Page page = Page;
if (page != null && page.RequiresControlState(this)) {
page.UnregisterRequiresControlState(this);
RareFieldsEnsured.RequiredControlState = true;
}
// Remove the generated ID so it will be assigned a different ID next time.
if (flags[useGeneratedID]) {
_id = null;
flags.Clear(useGeneratedID);
}
if (_occasionalFields != null && _occasionalFields.Controls != null) {
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++)
_occasionalFields.Controls[i].UnloadRecursive(dispose);
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
if(_adapter != null) {
_adapter.OnUnload(EventArgs.Empty);
}
else {
OnUnload(EventArgs.Empty);
}
//
if (dispose)
Dispose();
// VSWhidbey 244999: Everett behavior doesn't reset the control state.
// But for control which requires its OnInit method to be called again
// to properly initialize when the control is removed and added back
// to Page's control tree, the control can override IsReloadable
// to true so the control state is reset. e.g. Validator, see bug
if (IsReloadable) {
_controlState = ControlState.Constructed;
}
}
///
/// Assigns an sources of the event and its information up the page control
/// hierarchy until they reach the top of the control tree.
///
protected void RaiseBubbleEvent(object source, EventArgs args) {
Control currentTarget = Parent;
while (currentTarget != null) {
if (currentTarget.OnBubbleEvent(source, args)) {
return;
}
currentTarget = currentTarget.Parent;
}
}
///
/// Determines whether the event for the control should be passed up the page's
/// control hierarchy.
///
protected virtual bool OnBubbleEvent(object source, EventArgs args) {
return false;
}
// Members related to being a container
///
/// Gets a ControlCollection object that represents the child controls for a specified control in the
/// UI hierarchy.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Controls)
]
public virtual ControlCollection Controls {
get {
if (_occasionalFields == null || _occasionalFields.Controls == null) {
EnsureOccasionalFields();
_occasionalFields.Controls = CreateControlCollection();
}
return _occasionalFields.Controls;
}
}
///
/// Indicates a dictionary of state information that allows you to save and restore
/// the state of a control across multiple requests for the same page.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_State)
]
protected virtual StateBag ViewState {
get {
if (_viewState != null) { // create a StateBag on demand; WebControl makes its case sensitive
return _viewState;
}
_viewState = new StateBag(ViewStateIgnoresCase);
if (IsTrackingViewState)
_viewState.TrackViewState();
return _viewState;
}
}
// fast enough that we cam always use it.
///
/// Indicates whether the object is case-insensitive.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
protected virtual bool ViewStateIgnoresCase {
get {
return false;
}
}
///
///
protected internal virtual void AddedControl(Control control, int index) {
if (control.OwnerControl != null) {
throw new InvalidOperationException(SR.GetString(SR.Substitution_NotAllowed));
}
if (control._parent != null) {
control._parent.Controls.Remove(control);
}
control._parent = this;
control._page = Page;
control.flags.Clear(designModeChecked);
// We only add to naming container if it is available. Otherwise, it will be pushed through
// during InitRecursive
Control namingContainer = flags[isNamingContainer] ? this : _namingContainer;
if (namingContainer != null) {
control.UpdateNamingContainer(namingContainer);
if (control._id == null && !control.flags[idNotRequired]) {
// this will also dirty the name table in the naming container
control.GenerateAutomaticID();
}
else if (control._id != null || (control._occasionalFields != null && control._occasionalFields.Controls != null)) {
// If the control has and ID, or has children (which *may* themselves
// have ID's), we need to dirty the name table (ASURT 100557)
namingContainer.DirtyNameTable();
}
}
/*
* The following is for times when AddChild is called after CreateChildControls. This
* allows users to add children at any time in the creation process without having
* to understand the underlying machinery.
* Note that if page is null, it means we haven't been attached to a container ourselves.
* If this is true, when we are, our children will be recursively set up.
*/
if (_controlState >= ControlState.ChildrenInitialized) {
Debug.Assert(namingContainer != null);
control.InitRecursive(namingContainer);
// VSWhidbey 396372: We need to reregister the control state if the control is reparented because the control
// is unregistered during unload, but its already been inited once, so it will not get its Init called again
// which is where most controls call RegisterRequiresControlState
if (control._controlState >= ControlState.Initialized &&
control.RareFields != null &&
control.RareFields.RequiredControlState) {
Page.RegisterRequiresControlState(control);
}
if (_controlState >= ControlState.ViewStateLoaded) {
object viewState = null;
if(_occasionalFields != null && _occasionalFields.ControlsViewState != null) {
viewState = _occasionalFields.ControlsViewState[index];
// This solution takes the conservative approach that once viewstate has been
// applied to a child control, it is thrown away. This eliminates inadvertently
// setting viewstate on the wrong control, which can occur in scenarios where
// the child control collection is being manipulated via code. Probably need
// to provide a feature where programmer can control whether to reapply viewstate
// or not.
if (LoadViewStateByID) {
control.EnsureID();
viewState = _occasionalFields.ControlsViewState[control.ID];
_occasionalFields.ControlsViewState.Remove(control.ID);
}
else {
viewState = _occasionalFields.ControlsViewState[index];
_occasionalFields.ControlsViewState.Remove(index);
}
}
control.LoadViewStateRecursive(viewState);
if (_controlState >= ControlState.Loaded) {
control.LoadRecursive();
if (_controlState >= ControlState.PreRendered)
control.PreRenderRecursiveInternal();
}
}
}
}
///
/// [To be supplied.]
///
protected virtual ControlCollection CreateControlCollection() {
return new ControlCollection(this);
}
///
///
/// Notifies any controls that use composition-based implementation to create any
/// child controls they contain in preperation for postback or rendering.
///
///
protected internal virtual void CreateChildControls() {
}
///
/// Indicates whether the control's child controls have been created.
///
protected bool ChildControlsCreated {
get {
return flags[controlsCreated];
}
set {
if (!value && flags[controlsCreated]) {
Controls.Clear();
}
if(value) {
flags.Set(controlsCreated);
}
else {
flags.Clear(controlsCreated);
}
}
}
///
/// Make a URL absolute using the AppRelativeTemplateSourceDirectory. The returned URL is for
/// client use, and will contain the session cookie if appropriate.
///
public string ResolveUrl(string relativeUrl) {
if (relativeUrl == null) {
throw new ArgumentNullException("relativeUrl");
}
// check if its empty or already absolute
if ((relativeUrl.Length == 0) || (UrlPath.IsRelativeUrl(relativeUrl) == false)) {
return relativeUrl;
}
string baseUrl = AppRelativeTemplateSourceDirectory;
if (String.IsNullOrEmpty(baseUrl)) {
return relativeUrl;
}
// first make it absolute
string url = UrlPath.Combine(baseUrl, relativeUrl);
// include the session cookie if available (ASURT 47658)
// As a side effect, this will change an app relative path (~/...) to app absolute
return Context.Response.ApplyAppPathModifier(url);
}
///
/// Return a URL that is suitable for use on the client.
/// If the URL is absolute, return it unchanged. If it is relative, turn it into a
/// relative URL that is correct from the point of view of the current request path
/// (which is what the browser uses for resolution).
///
public string ResolveClientUrl(string relativeUrl) {
if (DesignMode && Page != null && Page.Site != null) {
IUrlResolutionService resolutionService = (IUrlResolutionService)Page.Site.GetService(typeof(IUrlResolutionService));
if (resolutionService != null) {
return resolutionService.ResolveClientUrl(relativeUrl);
}
}
if (relativeUrl == null) {
throw new ArgumentNullException("relativeUrl");
}
// Get the app absolute TemplateSourceDirectory (not app relative)
string tplSourceDir = VirtualPath.GetVirtualPathString(TemplateControlVirtualDirectory);
if (String.IsNullOrEmpty(tplSourceDir))
return relativeUrl;
string baseRequestDir = Context.Request.ClientBaseDir.VirtualPathString;
// If the path is app relative (~/...), we cannot take shortcuts, since
// the ~ is meaningless on the client, and must be resolved
if (!UrlPath.IsAppRelativePath(relativeUrl)) {
// If the template source directory is the same as the directory of the request,
// we don't need to do any adjustments to the input path
if (StringUtil.EqualsIgnoreCase(baseRequestDir, tplSourceDir))
return relativeUrl;
// check if it's empty or absolute
if ((relativeUrl.Length == 0) || (!UrlPath.IsRelativeUrl(relativeUrl))) {
return relativeUrl;
}
}
// first make it absolute
string url = UrlPath.Combine(tplSourceDir, relativeUrl);
// Make sure the path ends with a slash before calling MakeRelative
baseRequestDir = UrlPath.AppendSlashToPathIfNeeded(baseRequestDir);
// Now, make it relative to the current request, so that the client will
// compute the correct path
return HttpUtility.UrlPathEncode(UrlPath.MakeRelative(baseRequestDir, url));
}
internal void DirtyNameTable() {
Debug.Assert(this is INamingContainer);
if(_occasionalFields != null) {
_occasionalFields.NamedControls = null;
}
}
private void EnsureNamedControlsTable() {
Debug.Assert(this is INamingContainer);
Debug.Assert(HasControls());
Debug.Assert(_occasionalFields != null);
Debug.Assert(_occasionalFields.NamedControls == null);
_occasionalFields.NamedControls = new HybridDictionary(/*initialSize*/ _occasionalFields.NamedControlsID, /*caseInsensitive*/ true);
FillNamedControlsTable(this, _occasionalFields.Controls);
}
private void FillNamedControlsTable(Control namingContainer, ControlCollection controls) {
Debug.Assert(namingContainer._occasionalFields != null);
Debug.Assert(namingContainer._occasionalFields.NamedControls != null);
Debug.Assert((controls != null) && (controls.Count != 0));
int controlCount = controls.Count;
for (int i=0; i < controlCount; i++) {
Control control = controls[i];
if (control._id != null) {
#if DEBUG
if (control._namingContainer != null) {
Debug.Assert(control._namingContainer == namingContainer);
}
#endif // DEBUG
try {
namingContainer.EnsureOccasionalFields();
namingContainer._occasionalFields.NamedControls.Add(control._id, control);
}
catch {
throw new HttpException(SR.GetString(SR.Duplicate_id_used, control._id, "FindControl"));
}
}
if (control.HasControls() && (control.flags[isNamingContainer] == false)) {
FillNamedControlsTable(namingContainer, control.Controls);
}
}
}
///
/// Searches the current naming container for a control with
/// the specified .
///
public virtual Control FindControl(String id) {
return FindControl(id, 0);
}
///
///
/// Searches the current naming container for a control with the specified
/// and an offset to aid in the
/// search.
///
protected virtual Control FindControl(String id, int pathOffset) {
string childID;
EnsureChildControls();
// If we're not the naming container, let it do the job
if (!(flags[isNamingContainer])) {
Control namingContainer = NamingContainer;
if (namingContainer != null) {
return namingContainer.FindControl(id, pathOffset);
}
return null;
}
// No registered control, demand create the named controls table
//call HasControls ensuress _occasionalFields != null
if(HasControls() && _occasionalFields.NamedControls == null) {
EnsureNamedControlsTable();
}
if (_occasionalFields == null || _occasionalFields.NamedControls == null) {
return null;
}
// Need to support ':' for V1 backward compatibility.
char[] findControlSeparators = { ID_SEPARATOR, LEGACY_ID_SEPARATOR };
// Is it a hierarchical name?
int newPathOffset = id.IndexOfAny(findControlSeparators, pathOffset);
// If not, handle it here
if (newPathOffset == -1) {
childID = id.Substring(pathOffset);
return _occasionalFields.NamedControls[childID] as Control;
}
// Get the name of the child, and try to locate it
childID = id.Substring(pathOffset, newPathOffset - pathOffset);
Control child = _occasionalFields.NamedControls[childID] as Control;
// Child doesn't exist: fail
if (child == null)
return null;
return child.FindControl(id, newPathOffset + 1);
}
/*
* Called when the controls of a naming container are cleared.
*/
internal void ClearNamingContainer() {
Debug.Assert(this is INamingContainer);
EnsureOccasionalFields();
_occasionalFields.NamedControlsID = 0;
DirtyNameTable();
}
///
///
///
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
protected virtual IDictionary GetDesignModeState() {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.DesignModeState == null) {
rareFields.DesignModeState = new HybridDictionary();
}
return rareFields.DesignModeState;
}
///
/// Determines if the current control contains any child
/// controls. Since this method simply deteremines if any child controls exist at
/// all, it can enhance performance by avoiding a call to the Count property,
/// inherited from the class, on the
/// property.
///
public virtual bool HasControls() {
return _occasionalFields != null && _occasionalFields.Controls != null && _occasionalFields.Controls.Count > 0;
}
/*
* Check if a Control either has children or has a compiled render method.
* This is to address issues like ASURT 94127
*/
internal bool HasRenderingData() {
return HasControls() || HasRenderDelegate();
}
/*
* Check if a Control either has children or has a compiled render method.
* This is to address issues like ASURT 94127
*/
internal bool HasRenderDelegate() {
if(RareFields != null) {
return (RareFields.RenderMethod != null );
}
return false;
}
/*
* Returns true if the container contains just a static string, i.e.,
* when the Controls collection has a single LiteralControl.
*/
///
/// Determines if the container holds literal content only.
/// When this method returns
/// , the container collection only holds a single literal control. The
/// content is then passed to the requesting browser as HTML.
///
protected bool IsLiteralContent() {
return (_occasionalFields != null && _occasionalFields.Controls != null) && (_occasionalFields.Controls.Count == 1) &&
((_occasionalFields.Controls[0] is LiteralControl));
}
///
/// Determines if view state changes to the
///
/// are being saved.
///
protected bool IsTrackingViewState {
get {
return flags[marked];
}
}
///
/// Turns on tracking of view state changes to the control
/// so that they can be stored in the
/// object.
///
protected virtual void TrackViewState() {
if (_viewState != null)
_viewState.TrackViewState();
flags.Set(marked);
}
///
/// Checks that the control contains child controls; if it does not, it creates
/// them. This includes any literal content being parsed as a
/// object.
///
protected virtual void EnsureChildControls() {
if (!ChildControlsCreated && !flags[creatingControls]) {
flags.Set(creatingControls);
try {
ResolveAdapter();
if(_adapter != null) {
_adapter.CreateChildControls();
}
else {
CreateChildControls();
}
// Only set ChildControlsCreated = true if CreateChildControls() did not throw
// an exception (VSWhidbey 465798).
ChildControlsCreated = true;
}
finally {
flags.Clear(creatingControls);
}
}
}
///
/// Used internally to store a ControlBuilder reference for the control.
/// The builder will be used at design-time to help persist all the filtered properties
/// of the control.
///
internal void SetControlBuilder(ControlBuilder controlBuilder) {
RareFieldsEnsured.ControlBuilder = controlBuilder;
}
///
///
protected internal virtual void RemovedControl(Control control) {
if (control.OwnerControl != null) {
throw new InvalidOperationException(SR.GetString(SR.Substitution_NotAllowed));
}
if ((_namingContainer != null) && (control._id != null)) {
_namingContainer.DirtyNameTable();
}
// Controls may need to do their own cleanup.
control.UnloadRecursive(false);
control._parent = null;
control._page = null;
control._namingContainer = null;
// Don't reset _templateSourceVirtualDirectory on TemplateControl's, because
// the path is their own, not their parent. i.e. it doesn't change no matter
// where in the tree they end up.
if (!(control is TemplateControl))
control._templateSourceVirtualDirectory = null;
control._templateControl = null;
control.flags.Clear(mustRenderID);
control.ClearCachedUniqueIDRecursive();
}
internal void SetDesignMode() {
flags.Set(designMode);
flags.Set(designModeChecked);
}
///
///
///
protected virtual void SetDesignModeState(IDictionary data) {
}
// Set the delegate to the render method
///
///
/// Assigns any event handler delegates for the control to match the parameters
/// defined in the .
///
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void SetRenderMethodDelegate(RenderMethod renderMethod) {
RareFieldsEnsured.RenderMethod = renderMethod;
// Make the collection readonly if there are code blocks (ASURT 78810)
Controls.SetCollectionReadOnly(SR.Collection_readonly_Codeblocks);
}
///
///
/// Returns whether the control contains any data binding logic. This method is
/// only accessed by RAD designers.
///
bool IDataBindingsAccessor.HasDataBindings {
get {
return ((RareFields != null) && (RareFields.DataBindings != null) && (RareFields.DataBindings.Count != 0));
}
}
///
///
/// Indicates a collection of all data bindings on the control. This property is
/// read-only.
///
DataBindingCollection IDataBindingsAccessor.DataBindings {
get {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.DataBindings == null) {
rareFields.DataBindings = new DataBindingCollection();
}
return rareFields.DataBindings;
}
}
// IParserAccessor interface
// A sub-object tag was parsed by the parser; add it to this control.
///
///
/// Notifies the control that an element, XML or HTML, was parsed, and adds it to
/// the control.
///
void IParserAccessor.AddParsedSubObject(object obj) {
AddParsedSubObject(obj);
}
internal string SpacerImageUrl {
get {
EnsureOccasionalFields();
if (_occasionalFields.SpacerImageUrl == null) {
_occasionalFields.SpacerImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(WebControl), "Spacer.gif");
}
return _occasionalFields.SpacerImageUrl;
}
}
private Control OwnerControl {
get {
if (RareFields == null) {
return null;
}
return RareFields.OwnerControl;
}
set {
RareFieldsEnsured.OwnerControl = value;
}
}
internal IPostBackDataHandler PostBackDataHandler {
get {
IPostBackDataHandler pbdh = _adapter as IPostBackDataHandler;
if(pbdh != null)
return pbdh;
pbdh = this as IPostBackDataHandler;
return pbdh;
}
}
internal IPostBackEventHandler PostBackEventHandler {
get {
IPostBackEventHandler pbeh = _adapter as IPostBackEventHandler;
if(pbeh != null)
return pbeh;
pbeh = this as IPostBackEventHandler;
return pbeh;
}
}
#if ORCAS
internal bool NotVisibleOnPage {
get {
return flags[notVisibleOnPage];
}
set {
if(value) {
flags.Set(notVisibleOnPage);
}
else {
flags.Clear(notVisibleOnPage);
}
}
}
internal int VirtualStartPage {
get {
return RareFields != null ? RareFields.VirtualStartPage : -1;
}
set {
RareFieldsEnsured.VirtualStartPage = value;
}
}
internal int VirtualEndPage {
get {
return RareFields != null ? RareFields.VirtualEndPage : -1;
}
set {
RareFieldsEnsured.VirtualEndPage = value;
}
}
#endif
#region IControlDesignerAccessor implementation
///
IDictionary IControlDesignerAccessor.UserData {
get {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.ControlDesignerAccessorUserData == null) {
rareFields.ControlDesignerAccessorUserData = new HybridDictionary();
}
return rareFields.ControlDesignerAccessorUserData;
}
}
///
///
///
IDictionary IControlDesignerAccessor.GetDesignModeState() {
return GetDesignModeState();
}
///
///
///
void IControlDesignerAccessor.SetDesignModeState(IDictionary data) {
SetDesignModeState(data);
}
void IControlDesignerAccessor.SetOwnerControl(Control owner) {
if (owner == this) {
throw new ArgumentException(SR.GetString(SR.Control_CannotOwnSelf), "owner");
}
OwnerControl = owner;
_parent = owner.Parent;
_page = owner.Page;
}
#endregion
#region IControlBuilderAccessor implementation
///
///
/// A reference to the ControlBuilder that was used to construct this control (if there was one)
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
ControlBuilder IControlBuilderAccessor.ControlBuilder {
get {
return RareFields != null ? RareFields.ControlBuilder : null;
}
}
#endregion IControlBuilderAccessor implementation
#region IExpressionsAccessor
///
bool IExpressionsAccessor.HasExpressions {
get {
if (RareFields == null) {
return false;
}
ExpressionBindingCollection expressions = RareFields.ExpressionBindings;
return ((expressions != null) && (expressions.Count > 0));
}
}
///
ExpressionBindingCollection IExpressionsAccessor.Expressions {
get {
ExpressionBindingCollection expressions = RareFieldsEnsured.ExpressionBindings;
if (expressions == null) {
expressions = new ExpressionBindingCollection();
RareFields.ExpressionBindings = expressions;
}
return expressions;
}
}
#endregion
private sealed class ControlRareFields : IDisposable {
internal ControlRareFields() {
}
public ISite Site;
public RenderMethod RenderMethod;
// Reference to the templateControl that hosts this control.
#if ORCAS
public int VirtualStartPage = -1;
public int VirtualEndPage = -1;
public ContentPager ContentPager;
#endif
// Reference to the ControlBuilder used to build this control
public ControlBuilder ControlBuilder;
public DataBindingCollection DataBindings;
public Control OwnerControl;
public ExpressionBindingCollection ExpressionBindings;
public bool RequiredControlState = false;
// These fields are only used in the designer so we
// keep them here to prevent memory bloat at runtime
public IDictionary ControlDesignerAccessorUserData;
public IDictionary DesignModeState;
public void Dispose() {
//do not null out for backwards compat, VSWhidbey 475940
//Site = null;
//RenderMethod = null;
//DataBindings = null;
//OwnerControl = null;
//ExpressionBindings = null;
ControlBuilder = null;
if (OwnerControl != null)
{
OwnerControl.Dispose();
}
ControlDesignerAccessorUserData = null;
DesignModeState = null;
#if ORCAS
ContentPager = null;
#endif
}
}
private sealed class OccasionalFields : IDisposable {
internal OccasionalFields() {
}
public string SkinId;
// Events
public EventHandlerList Events;
public IDictionary ControlsViewState;
public ControlCollection Controls;
public int NamedControlsID;
// Only used if we are a naming container. It contains all the controls
// in the namespace.
public IDictionary NamedControls;
public ControlRareFields RareFields;
public String UniqueIDPrefix;
public string SpacerImageUrl;
public void Dispose() {
if (Events != null) {
Events.Dispose();
Events = null;
}
if (RareFields != null) {
RareFields.Dispose();
}
ControlsViewState = null;
//do not null out for backwards compat, VSWhidbey 475940
//Controls = null;
//NamedControls = null;
//UniqueIDPrefix = null;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Web.UI {
using System.Text;
using System.ComponentModel;
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
using System.IO;
using HttpException = System.Web.HttpException;
using System.Web.Configuration;
using System.Web.UI.Adapters;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.Util;
using System.Web.Hosting;
using System.Web.Caching;
using System.Security.Permissions;
// Delegate used for the compiled template
public delegate void RenderMethod(HtmlTextWriter output, Control container);
public delegate Control BuildMethod();
// Defines the properties, methods, and events that are shared by all server
// controls in the Web Forms page framework.
[
Bindable(true),
DefaultProperty("ID"),
DesignerCategory("Code"),
Designer("System.Web.UI.Design.ControlDesigner, " + AssemblyRef.SystemDesign),
DesignerSerializer("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, " + AssemblyRef.MicrosoftVisualStudioWeb, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + AssemblyRef.SystemDesign),
Themeable(false),
ToolboxItemFilter("System.Web.UI", ToolboxItemFilterType.Require),
ToolboxItemAttribute("System.Web.UI.Design.WebControlToolboxItem, " + AssemblyRef.SystemDesign)
]
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public class Control : IComponent, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor {
internal static readonly object EventDataBinding = new object();
internal static readonly object EventInit = new object();
internal static readonly object EventLoad = new object();
internal static readonly object EventUnload = new object();
internal static readonly object EventPreRender = new object();
private static readonly object EventDisposed = new object();
internal const bool EnableViewStateDefault = true;
internal const char ID_SEPARATOR = '$';
private const char ID_RENDER_SEPARATOR = '_';
internal const char LEGACY_ID_SEPARATOR = ':';
private string _id;
// allows us to reuse the id variable to store a calculated id w/o polluting the public getter
private string _cachedUniqueID;
private Control _parent;
// fields related to being a container
private ControlState _controlState;
private StateBag _viewState;
// The naming container that this control leaves in. Note that even if
// this ctrl is a naming container, it will not point to itself, but to
// the naming container that contains it.
private Control _namingContainer;
internal Page _page;
private OccasionalFields _occasionalFields;
private TemplateControl _templateControl;
// The virtual directory of the Page or UserControl that hosts this control.
private VirtualPath _templateSourceVirtualDirectory;
internal ControlAdapter _adapter;
// const masks into the BitVector32
private const int idNotCalculated = 0x00000001;
private const int marked = 0x00000002;
private const int disableViewState = 0x00000004;
private const int controlsCreated = 0x00000008;
private const int invisible = 0x00000010;
private const int visibleDirty = 0x00000020;
private const int idNotRequired = 0x00000040;
private const int isNamingContainer = 0x00000080;
private const int creatingControls = 0x00000100;
private const int notVisibleOnPage = 0x00000200;
private const int themeApplied = 0x00000400;
private const int mustRenderID = 0x00000800;
private const int disableTheming = 0x00001000;
private const int enableThemingSet = 0x00002000;
private const int styleSheetApplied = 0x00004000;
private const int controlAdapterResolved = 0x00008000;
private const int designMode = 0x00010000;
private const int designModeChecked = 0x00020000;
private const int disableChildControlState = 0x00040000;
internal const int isWebControlDisabled = 0x00080000;
private const int controlStateApplied = 0x00100000;
private const int useGeneratedID = 0x00200000;
#pragma warning disable 0649
internal SimpleBitVector32 flags;
#pragma warning restore 0649
private const string automaticIDPrefix = "ctl";
private const string automaticLegacyIDPrefix = "_ctl";
private const int automaticIDCount = 128;
private static readonly string[] automaticIDs = new string [automaticIDCount] {
"ctl00", "ctl01", "ctl02", "ctl03", "ctl04", "ctl05", "ctl06",
"ctl07", "ctl08", "ctl09", "ctl10", "ctl11", "ctl12", "ctl13",
"ctl14", "ctl15", "ctl16", "ctl17", "ctl18", "ctl19", "ctl20",
"ctl21", "ctl22", "ctl23", "ctl24", "ctl25", "ctl26", "ctl27",
"ctl28", "ctl29", "ctl30", "ctl31", "ctl32", "ctl33", "ctl34",
"ctl35", "ctl36", "ctl37", "ctl38", "ctl39", "ctl40", "ctl41",
"ctl42", "ctl43", "ctl44", "ctl45", "ctl46", "ctl47", "ctl48",
"ctl49", "ctl50", "ctl51", "ctl52", "ctl53", "ctl54", "ctl55",
"ctl56", "ctl57", "ctl58", "ctl59", "ctl60", "ctl61", "ctl62",
"ctl63", "ctl64", "ctl65", "ctl66", "ctl67", "ctl68", "ctl69",
"ctl70", "ctl71", "ctl72", "ctl73", "ctl74", "ctl75", "ctl76",
"ctl77", "ctl78", "ctl79", "ctl80", "ctl81", "ctl82", "ctl83",
"ctl84", "ctl85", "ctl86", "ctl87", "ctl88", "ctl89", "ctl90",
"ctl91", "ctl92", "ctl93", "ctl94", "ctl95", "ctl96", "ctl97",
"ctl98", "ctl99",
"ctl100", "ctl101", "ctl102", "ctl103", "ctl104", "ctl105", "ctl106",
"ctl107", "ctl108", "ctl109", "ctl110", "ctl111", "ctl112", "ctl113",
"ctl114", "ctl115", "ctl116", "ctl117", "ctl118", "ctl119", "ctl120",
"ctl121", "ctl122", "ctl123", "ctl124", "ctl125", "ctl126", "ctl127"
};
///
/// Initializes a new instance of the class.
///
public Control() {
if (this is INamingContainer)
flags.Set(isNamingContainer);
}
///
/// Indicates the control identifier generated by the ASP.NET framework. This
/// property is read-only.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_ClientID)
]
public virtual string ClientID {
// This property is required to render a unique client-friendly id.
get {
// Ensure that ID is set. The assumption being made is that the caller
// is likely to use the client ID in script, and to support that the
// control should render out an ID attribute
EnsureID();
string uniqueID = UniqueID;
if(uniqueID != null && uniqueID.IndexOf(IdSeparator) >= 0) {
return uniqueID.Replace(IdSeparator, ID_RENDER_SEPARATOR);
}
return uniqueID;
}
}
protected char ClientIDSeparator {
get {
return ID_RENDER_SEPARATOR;
}
}
///
/// [To be supplied.]
///
[
WebSysDescription(SR.Control_OnDisposed)
]
public event EventHandler Disposed {
add {
Events.AddHandler(EventDisposed, value);
}
remove {
Events.RemoveHandler(EventDisposed, value);
}
}
///
/// Gets the object of the current Web request. If
/// the control's context is , this will be the context of the
/// control's parent, unless the parent control's context is .
/// If this is the case, this will be equal to the HttpContext property.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
protected internal virtual HttpContext Context {
// Request context containing the intrinsics
get {
Page page = Page;
if(page != null) {
return page.Context;
}
return HttpContext.Current;
}
}
protected virtual ControlAdapter ResolveAdapter() {
if(flags[controlAdapterResolved]) {
return _adapter;
}
if (DesignMode) {
flags.Set(controlAdapterResolved);
return null;
}
HttpContext context = Context;
if (context != null) {
_adapter = context.Request.Browser.GetAdapter(this);
}
flags.Set(controlAdapterResolved);
return _adapter;
}
///
/// Indicates the list of event handler delegates for the control. This property
/// is read-only.
///
protected ControlAdapter Adapter {
get {
if(flags[controlAdapterResolved]) {
return _adapter;
}
_adapter = ResolveAdapter();
flags.Set(controlAdapterResolved);
return _adapter;
}
}
///
/// Indicates whether a control is being used in the context of a design surface.
///
protected internal bool DesignMode {
get {
if(!flags[designModeChecked]) {
Page page = Page;
if(page != null ) {
if(page.GetDesignModeInternal()) {
flags.Set(designMode);
}
else {
flags.Clear(designMode);
}
}
else {
if(Site != null) {
if(Site.DesignMode) {
flags.Set(designMode);
}
else {
flags.Clear(designMode);
}
}
else if (Parent != null) {
if(Parent.DesignMode) {
flags.Set(designMode);
}
// VSWhidbey 535747: If Page, Site and Parent are all null, do not change the
// designMode flag since it might had been previously set by the controlBuilder.
// This does not affect runtime since designMode is by-default false.
/*
else {
flags.Clear(designMode);
}
*/
}
}
flags.Set(designModeChecked);
}
return flags[designMode];
}
}
// Helper function to call validateEvent.
internal void ValidateEvent(string uniqueID) {
ValidateEvent(uniqueID, String.Empty);
}
// Helper function to call validateEvent.
internal void ValidateEvent(string uniqueID, string eventArgument) {
if (Page != null && SupportsEventValidation) {
Page.ClientScript.ValidateEvent(uniqueID, eventArgument);
}
}
// Indicates whether the control supports event validation
// By default, all web controls in System.Web assembly supports it but not custom controls.
private bool SupportsEventValidation {
get {
return SupportsEventValidationAttribute.SupportsEventValidation(this.GetType());
}
}
///
/// Indicates the list of event handler delegates for the control. This property
/// is read-only.
///
protected EventHandlerList Events {
get {
EnsureOccasionalFields();
if(_occasionalFields.Events == null) {
_occasionalFields.Events = new EventHandlerList();
}
return _occasionalFields.Events;
}
}
protected bool HasEvents() {
return ((_occasionalFields != null) && (_occasionalFields.Events != null));
}
///
/// Gets or sets the identifier for the control. Setting the
/// property on a control allows programmatic access to the control's properties. If
/// this property is not specified on a control, either declaratively or
/// programmatically, then you cannot write event handlers and the like for the control.
///
[
ParenthesizePropertyName(true),
MergableProperty(false),
Filterable(false),
Themeable(false),
WebSysDescription(SR.Control_ID)
]
public virtual string ID {
get {
if (!flags[idNotCalculated] && !flags[mustRenderID]) {
return null;
}
return _id;
}
set {
// allow the id to be unset
if (value != null && value.Length == 0)
value = null;
string oldID = _id;
_id = value;
ClearCachedUniqueIDRecursive();
flags.Set(idNotCalculated);
flags.Clear(useGeneratedID);
// Update the ID in the naming container
if ((_namingContainer != null) && (oldID != null)) {
_namingContainer.DirtyNameTable();
}
}
}
///
/// Gets and sets a value indicating whether theme is enabled.
///
[
Browsable(false),
DefaultValue(true),
Themeable(false),
WebCategory("Behavior"),
WebSysDescription(SR.Control_EnableTheming)
]
public virtual bool EnableTheming {
get {
if (flags[enableThemingSet]) {
return !flags[disableTheming];
}
if (Parent != null) {
return Parent.EnableTheming;
}
return !flags[disableTheming];
}
set {
if ((_controlState >= ControlState.FrameworkInitialized) && !DesignMode) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePreInitOrAddToControls, "EnableTheming"));
}
if(!value) {
flags.Set(disableTheming);
}
else {
flags.Clear(disableTheming);
}
flags.Set(enableThemingSet);
}
}
// Serialzie the value if it's set explicitely.
internal bool ShouldSerializeEnableTheming() {
return flags[enableThemingSet];;
}
internal bool IsBindingContainer {
get {
return this is INamingContainer && !(this is INonBindingContainer);
}
}
protected internal bool IsChildControlStateCleared {
get {
return flags[disableChildControlState];
}
}
///
/// Gets and sets the skinID of the control.
///
[
Browsable(false),
DefaultValue(""),
Filterable(false),
WebCategory("Behavior"),
WebSysDescription(SR.Control_SkinId),
]
public virtual string SkinID {
get {
if(_occasionalFields != null) {
return _occasionalFields.SkinId == null ? String.Empty : _occasionalFields.SkinId;
}
return String.Empty;
}
set {
if (!DesignMode) {
if (flags[styleSheetApplied]) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforeStyleSheetApplied, "SkinId"));
}
if (_controlState >= ControlState.FrameworkInitialized) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePreInitOrAddToControls, "SkinId"));
}
}
EnsureOccasionalFields();
_occasionalFields.SkinId = value;
}
}
private ControlRareFields RareFieldsEnsured {
get {
EnsureOccasionalFields();
ControlRareFields rareFields = _occasionalFields.RareFields;
if(rareFields == null) {
rareFields = new ControlRareFields();
_occasionalFields.RareFields = rareFields;
}
return rareFields;
}
}
private ControlRareFields RareFields {
get {
if(_occasionalFields != null) {
return _occasionalFields.RareFields;
}
return null;
}
}
private void EnsureOccasionalFields() {
if(_occasionalFields == null) {
_occasionalFields = new OccasionalFields();
}
}
///
///
/// Gets or sets a value indicating whether the control should maintain its view
/// state, and the view state of any child control in contains, when the current
/// page request ends.
///
///
[
DefaultValue(EnableViewStateDefault),
Themeable(false),
WebCategory("Behavior"),
WebSysDescription(SR.Control_MaintainState)
]
public virtual bool EnableViewState {
get {
return !flags[disableViewState];
}
set {
SetEnableViewStateInternal(value);
}
}
internal void SetEnableViewStateInternal(bool value) {
if (!value)
flags.Set(disableViewState);
else
flags.Clear(disableViewState);
}
///
/// Gets a value indicating whether the control is maintaining its view
/// state, when the current page request ends by looking at its own EnableViewState
/// value, and the value for all its parents.
///
protected internal bool IsViewStateEnabled {
get {
Control current = this;
while (current != null) {
if (current.EnableViewState == false) {
return false;
}
current = current.Parent;
}
return true;
}
}
///
/// Gets the reference to the current control's naming container.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_NamingContainer)
]
public virtual Control NamingContainer {
get {
if (_namingContainer == null) {
if (Parent != null) {
// Search for the closest naming container in the tree
if (Parent.flags[isNamingContainer])
_namingContainer = Parent;
else
_namingContainer = Parent.NamingContainer;
}
}
return _namingContainer;
}
}
///
///
/// Returns the databinding container of this control. In most cases,
/// this is the same as the NamingContainer. But when using LoadTemplate(),
/// we get into a situation where that is not the case (ASURT 94138)
/// The behavior is different than V1 that Usercontrol.BindingContainer is no
/// longer the UserControl but the control contains it. The behavior is consistent
/// with LoadTemplate() case.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never)
]
public Control BindingContainer {
get {
Control bindingContainer = NamingContainer;
while (bindingContainer is INonBindingContainer) {
bindingContainer = bindingContainer.BindingContainer;
}
return bindingContainer;
}
}
///
///
/// VSWhidbey 80467: Need to adapt id separator.
///
protected char IdSeparator {
get {
if (Page != null) {
return Page.IdSeparator;
}
return IdSeparatorFromConfig;
}
}
// VSWhidbey 475945: Use the old id separator if configured
internal char IdSeparatorFromConfig {
get {
return ((EnableLegacyRendering) ? LEGACY_ID_SEPARATOR : ID_SEPARATOR);
}
}
// VSWhidbey 244374: Allow controls to opt into loading view state by ID instead of index (perf hit)
protected bool LoadViewStateByID {
get {
return ViewStateModeByIdAttribute.IsEnabled(GetType());
}
}
///
/// Gets the object that contains the
/// current control.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Page)
]
public virtual Page Page {
get {
if (_page == null) {
if (Parent != null) {
_page = Parent.Page;
}
}
return _page;
}
set {
if (OwnerControl != null) {
throw new InvalidOperationException();
}
// This is necessary because we need to set the page in generated
// code before controls are added to the tree (ASURT 75330)
Debug.Assert(_page == null);
Debug.Assert(Parent == null || Parent.Page == null);
_page = value;
}
}
// VSWhidbey 244999
internal virtual bool IsReloadable {
get {
return false;
}
}
// DevDiv 33149, 43258: A backward compat. switch for Everett rendering
internal bool EnableLegacyRendering {
get {
Page page = Page;
if (page != null) {
return (page.XhtmlConformanceMode == XhtmlConformanceMode.Legacy);
}
else if (DesignMode || Adapter != null) {
return false;
}
else {
return (GetXhtmlConformanceSection().Mode == XhtmlConformanceMode.Legacy);
}
}
}
internal XhtmlConformanceSection GetXhtmlConformanceSection() {
HttpContext context = Context;
XhtmlConformanceSection xhtmlConformanceSection;
if (context != null) {
// if context is available, use the most efficient way to get the section
xhtmlConformanceSection = RuntimeConfig.GetConfig(context).XhtmlConformance;
}
else {
xhtmlConformanceSection = RuntimeConfig.GetConfig().XhtmlConformance;
}
Debug.Assert(xhtmlConformanceSection != null);
return xhtmlConformanceSection;
}
#if ORCAS
///
/// Gets the object that
/// paginates the current control.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Pager)
]
public virtual ContentPager ContentPager {
get {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.ContentPager == null) {
if (Parent != null) {
rareFields.ContentPager = Parent.ContentPager;
}
}
return rareFields.ContentPager;
}
set {
RareFieldsEnsured.ContentPager = value;
}
}
#endif
///
/// Gets the reference to the
/// that hosts the control.
///
internal virtual TemplateControl GetTemplateControl() {
if(_templateControl == null) {
if (Parent != null) {
_templateControl = Parent.GetTemplateControl();
}
}
return _templateControl;
}
///
/// Gets the reference to the
/// that hosts the control.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_TemplateControl)
]
public TemplateControl TemplateControl {
get {
return GetTemplateControl();
}
[EditorBrowsable(EditorBrowsableState.Never)]
set {
// This setter is necessary so that controls inside templates are based on
// hosting pages not where the templates are used.
_templateControl = value;
}
}
/*
* Determine whether this control is a descendent of the passed in control
*/
internal bool IsDescendentOf(Control ancestor) {
Control current = this;
while (current != ancestor && current.Parent != null) {
current = current.Parent;
}
return (current == ancestor);
}
///
/// Gets the current control's parent control in the UI hierarchy.
///
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Parent)
]
public virtual Control Parent {
get {
return _parent;
}
}
internal bool IsParentedToUpdatePanel {
get {
Control parent = Parent;
while (parent != null) {
if (parent is IUpdatePanel) {
return true;
}
parent = parent.Parent;
}
return false;
}
}
///
/// Gets the virtual directory of the Page or UserControl that contains this control.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_TemplateSourceDirectory)
]
public virtual string TemplateSourceDirectory {
get {
if (TemplateControlVirtualDirectory == null)
return String.Empty;
return TemplateControlVirtualDirectory.VirtualPathStringNoTrailingSlash;
}
}
///
/// Gets the virtual directory of the Page or UserControl that contains this control.
/// Unlike TemplateSourceDirectory, this returns an app relative path (e.g. "~/sub")
///
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Advanced),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_TemplateSourceDirectory)
]
public string AppRelativeTemplateSourceDirectory {
get {
return VirtualPath.GetAppRelativeVirtualPathStringOrEmpty(TemplateControlVirtualDirectory);
}
[EditorBrowsable(EditorBrowsableState.Never)]
set {
// This setter is necessary so that skins are based on hosting skin file.
this.TemplateControlVirtualDirectory = VirtualPath.CreateNonRelativeAllowNull(value);
}
}
internal VirtualPath TemplateControlVirtualDirectory {
get {
if (_templateSourceVirtualDirectory != null)
return _templateSourceVirtualDirectory;
TemplateControl control = TemplateControl;
if (control == null) {
HttpContext context = Context;
if (context != null) {
_templateSourceVirtualDirectory = context.Request.CurrentExecutionFilePathObject.Parent;
}
return _templateSourceVirtualDirectory;
}
// Prevent recursion if this is the TemplateControl
if (control != this) {
_templateSourceVirtualDirectory = control.TemplateControlVirtualDirectory;
}
return _templateSourceVirtualDirectory;
}
set {
// This setter is necessary so that skins are based on hosting skin file.
_templateSourceVirtualDirectory = value;
}
}
internal ControlState ControlState {
get { return _controlState; }
set { _controlState = value; }
}
///
/// Indicates the site information for the control.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Advanced),
WebSysDescription(SR.Control_Site)
]
public ISite Site {
get {
if (OwnerControl != null) {
return OwnerControl.Site;
}
if (RareFields != null) {
return RareFields.Site;
}
return null;
}
set {
if (OwnerControl != null) {
throw new InvalidOperationException(SR.GetString(SR.Substitution_SiteNotAllowed));
}
RareFieldsEnsured.Site = value;
flags.Clear(designModeChecked);
}
}
///
///
/// Gets or sets a value that indicates whether a control should be rendered on
/// the page.
///
///
[
Bindable(true),
DefaultValue(true),
WebCategory("Behavior"),
WebSysDescription(SR.Control_Visible)
]
public virtual bool Visible {
get {
if (flags[invisible])
return false;
#if ORCAS
if (NotVisibleOnPage)
return false;
#endif
else if ((_parent != null) && !DesignMode)
return _parent.Visible;
else
return true;
}
set {
if (flags[marked]) {
bool visible = !flags[invisible];
if (visible != value) {
flags.Set(visibleDirty);
}
}
if(!value) {
flags.Set(invisible);
}
else {
flags.Clear(invisible);
}
}
}
#if ORCAS
internal bool ExplicitlyInvisible {
get {
return flags[invisible];
}
}
#endif
///
/// Do not remove or change the signature. It is called via reflection.
/// This allows for correct serialization, since Visible is implemented as a
/// recursive property.
///
private void ResetVisible() {
Visible = true;
}
///
/// Do not remove or change the signature. It is called via reflection.
/// This allows for correct serialization, since Visible is implemented as a
/// recursive property.
///
private bool ShouldSerializeVisible() {
return flags[invisible];
}
///
/// Gets the unique, hierarchically-qualified identifier for
/// a control. This is different from the ID property, in that the fully-qualified
/// identifier includes the identifier for the control's naming container.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_UniqueID)
]
public virtual string UniqueID {
get {
if (_cachedUniqueID != null) {
return _cachedUniqueID;
}
Control namingContainer = NamingContainer;
if (namingContainer != null) {
// if the ID is null at this point, we need to have one created and the control added to the
// naming container.
if (_id == null) {
GenerateAutomaticID();
}
if (Page == namingContainer) {
_cachedUniqueID = _id;
}
else {
string uniqueIDPrefix = namingContainer.GetUniqueIDPrefix();
if (uniqueIDPrefix.Length == 0) {
// In this case, it is probably a naming container that is not sited, so we don't want to cache it
return _id;
}
else {
_cachedUniqueID = uniqueIDPrefix + _id;
}
}
return _cachedUniqueID;
}
else {
// no naming container
return _id;
}
}
}
#if SHIPPINGADAPTERS
// Used by adapters in delegating rendering (e.g., a Button for a LinkButton for scriptless devices).
// The UniqueID of the new control has to be set to match the UniqueID of the original.
internal void SetUniqueID(string val) {
_cachedUniqueID = val;
}
#endif
///
/// Occurs when the control binds to a data source. Notifies the control to perform any data binding during this event.
///
[
WebCategory("Data"),
WebSysDescription(SR.Control_OnDataBind)
]
public event EventHandler DataBinding {
add {
Events.AddHandler(EventDataBinding, value);
}
remove {
Events.RemoveHandler(EventDataBinding, value);
}
}
///
/// Occurs when the control is initialized, the first step in the page lifecycle. Controls should
/// perform any initialization steps that are required to create and set up an
/// instantiation.
///
[
WebSysDescription(SR.Control_OnInit)
]
public event EventHandler Init {
add {
Events.AddHandler(EventInit, value);
}
remove {
Events.RemoveHandler(EventInit, value);
}
}
///
/// Occurs when the control is loaded to the object. Notifies the control to perform any steps that
/// need to occur on each page request.
///
[
WebSysDescription(SR.Control_OnLoad)
]
public event EventHandler Load {
add {
Events.AddHandler(EventLoad, value);
}
remove {
Events.RemoveHandler(EventLoad, value);
}
}
///
/// Occurs when the control is about to render. Controls
/// should perform any pre-rendering steps necessary before saving view state and
/// rendering content to the object.
///
[
WebSysDescription(SR.Control_OnPreRender)
]
public event EventHandler PreRender {
add {
Events.AddHandler(EventPreRender, value);
}
remove {
Events.RemoveHandler(EventPreRender, value);
}
}
///
/// Occurs when the control is unloaded from memory. Controls should perform any
/// final cleanup before this instance of it is
///
[
WebSysDescription(SR.Control_OnUnload)
]
public event EventHandler Unload {
add {
Events.AddHandler(EventUnload, value);
}
remove {
Events.RemoveHandler(EventUnload, value);
}
}
///
/// Apply stylesheet skin on the control.
///
[
EditorBrowsable(EditorBrowsableState.Advanced),
]
public virtual void ApplyStyleSheetSkin(Page page) {
// Nothing to do if the control is not in a Page.
if (page == null) {
return;
}
// Only apply stylesheet if not already applied.
if (flags[styleSheetApplied]) {
throw new InvalidOperationException(SR.GetString(SR.StyleSheetAreadyAppliedOnControl));
}
if (page.ApplyControlStyleSheet(this)) {
flags.Set(styleSheetApplied);
}
}
///
/// Apply theme on the control.
///
private void ApplySkin(Page page) {
if (page == null) {
throw new ArgumentNullException("page");
}
if (flags[themeApplied]) {
return;
}
if (ThemeableAttribute.IsTypeThemeable(this.GetType())) {
page.ApplyControlSkin(this);
flags.Set(themeApplied);
}
}
///
/// Raises the event. This
/// notifies a control to perform any data binding logic that is associated with it.
///
protected virtual void OnDataBinding(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventDataBinding] as EventHandler;
if(handler != null) {
handler(this, e);
}
}
}
///
/// Causes data binding to occur on the invoked control and all of its child
/// controls.
///
public virtual void DataBind() {
DataBind(true);
}
///
/// Causes the invoked controls' context to be pushed on the stack,
/// then conditionally call OnDataBinging on the invoked control, and databind all of its child
/// controls. A control would call this with false if it overrides DataBind without calling
/// Control.DataBind, but still wants to be an IDataItemContainer. FormView and DetailsView
/// are good examples of this.
///
protected virtual void DataBind(bool raiseOnDataBinding) {
bool inDataBind = false;
if (IsBindingContainer) {
bool foundDataItem;
object dataItem = DataBinder.GetDataItem(this, out foundDataItem);
if (foundDataItem && (Page != null)) {
Page.PushDataBindingContext(dataItem);
inDataBind = true;
}
}
try {
if (raiseOnDataBinding) {
// Do our own databinding
OnDataBinding(EventArgs.Empty);
}
// Do all of our children's databinding
DataBindChildren();
}
finally {
if (inDataBind) {
Page.PopDataBindingContext();
}
}
}
///
/// Causes data binding to occur on all of the child controls.
///
protected virtual void DataBindChildren() {
if (HasControls()) {
EnsureOccasionalFields();
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
try {
try {
int controlCount = _occasionalFields.Controls.Count;
for (int i=0; i < controlCount; i++)
_occasionalFields.Controls[i].DataBind();
}
finally {
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
}
catch {
throw;
}
}
}
internal void PreventAutoID() {
// controls that are also naming containers must always get an id
if (flags[isNamingContainer] == false) {
flags.Set(idNotRequired);
}
}
///
/// Notifies the control that an element, XML or HTML, was parsed, and adds it to
/// the control.
///
protected virtual void AddParsedSubObject(object obj) {
Control control = obj as Control;
if (control != null) {
Controls.Add(control);
}
}
private void UpdateNamingContainer(Control namingContainer) {
// Remove the cached uniqueID if the control already had a namingcontainer
// and the namingcontainer is changed.
if (_namingContainer != null && _namingContainer != namingContainer) {
ClearCachedUniqueIDRecursive();
}
_namingContainer = namingContainer;
}
private void ClearCachedUniqueIDRecursive() {
_cachedUniqueID = null;
if (_occasionalFields != null) {
_occasionalFields.UniqueIDPrefix = null;
if (_occasionalFields.Controls != null) {
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
_occasionalFields.Controls[i].ClearCachedUniqueIDRecursive();
}
}
}
}
protected void EnsureID() {
if (_namingContainer != null) {
if (_id == null) {
GenerateAutomaticID();
}
flags.Set(mustRenderID);
}
}
private void GenerateAutomaticID() {
Debug.Assert(_namingContainer != null);
Debug.Assert(_id == null);
// Remember that a generated ID is used for this control.
flags.Set(useGeneratedID);
// Calculate the automatic ID. For performance and memory reasons
// we look up a static table entry if possible
_namingContainer.EnsureOccasionalFields();
int idNo = _namingContainer._occasionalFields.NamedControlsID++;
if (EnableLegacyRendering) {
// VSWhidbey 517118
_id = automaticLegacyIDPrefix + idNo.ToString(NumberFormatInfo.InvariantInfo);
}
else {
if (idNo < automaticIDCount) {
_id = automaticIDs[idNo];
}
else {
_id = automaticIDPrefix + idNo.ToString(NumberFormatInfo.InvariantInfo);
}
}
_namingContainer.DirtyNameTable();
}
internal virtual string GetUniqueIDPrefix() {
EnsureOccasionalFields();
if (_occasionalFields.UniqueIDPrefix == null) {
string uniqueID = UniqueID;
if (!String.IsNullOrEmpty(uniqueID)) {
_occasionalFields.UniqueIDPrefix = uniqueID + IdSeparator;
}
else {
_occasionalFields.UniqueIDPrefix = String.Empty;
}
}
return _occasionalFields.UniqueIDPrefix;
}
///
/// Raises the event. This notifies the control to perform
/// any steps necessary for its creation on a page request.
///
protected internal virtual void OnInit(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventInit] as EventHandler;
if(handler != null) {
handler(this, e);
}
}
}
internal virtual void InitRecursive(Control namingContainer) {
ResolveAdapter();
if (_occasionalFields != null && _occasionalFields.Controls != null) {
if (flags[isNamingContainer]) {
namingContainer = this;
}
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
Control control = _occasionalFields.Controls[i];
// Propagate the page and namingContainer
control.UpdateNamingContainer(namingContainer);
if ((control._id == null) && (namingContainer != null) && !control.flags[idNotRequired]) {
control.GenerateAutomaticID();
}
control._page = Page;
control.InitRecursive(namingContainer);
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
// Only make the actual call if it hasn't already happened (ASURT 111303)
if (_controlState < ControlState.Initialized) {
_controlState = ControlState.ChildrenInitialized; // framework also initialized
if ((Page != null) && !DesignMode) {
if (Page.ContainsTheme && EnableTheming) {
ApplySkin(Page);
}
}
if (_adapter != null) {
_adapter.OnInit(EventArgs.Empty);
}
else {
OnInit(EventArgs.Empty);
}
_controlState = ControlState.Initialized;
}
// track all subsequent state changes
TrackViewState();
#if DEBUG
ControlInvariant();
#endif
}
#if DEBUG
///
/// This should be used to assert internal state about the control
///
internal void ControlInvariant() {
// If the control is initialized, the naming container and page should have been pushed in
if (_controlState >= ControlState.Initialized) {
if (DesignMode) {
// Top-level UserControls do not have a page or a naming container in the designer
// hence the special casing.
Debug.Assert((_namingContainer != null) || (this is Page) || (this is UserControl));
//
}
else {
if (!(this is Page)) {
Debug.Assert(_namingContainer != null);
}
Debug.Assert(Page != null);
}
}
// If naming container is set and the name table exists, the ID should exist in it.
if(_namingContainer != null &&
_namingContainer._occasionalFields != null &&
_namingContainer._occasionalFields.NamedControls != null &&
_id != null) {
Debug.Assert(_namingContainer._occasionalFields.NamedControls.Contains(_id));
}
}
// Collect some statistic about the number of controls with occasional and
// rare fields.
internal void GetRareFieldStatistics(ref int totalControls,
ref int withOccasionalFields, ref int withRareFields) {
totalControls++;
if (_occasionalFields != null) {
withOccasionalFields++;
if (_occasionalFields.RareFields != null)
withRareFields++;
// No children: we're done
if (_occasionalFields.Controls == null)
return;
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
Control control = _occasionalFields.Controls[i];
control.GetRareFieldStatistics(ref totalControls, ref withOccasionalFields,
ref withRareFields);
}
}
}
#endif
protected void ClearChildState() {
ClearChildControlState();
ClearChildViewState();
}
protected void ClearChildControlState() {
//VSWhidbey 242621 to be consistent with ClearChildViewState, ignore calls before and during Init
if (ControlState < ControlState.Initialized) {
return;
}
flags.Set(disableChildControlState);
if (Page != null) {
Page.RegisterRequiresClearChildControlState(this);
}
}
///
/// Deletes the view state information for all of the current control's child
/// controls.
///
protected void ClearChildViewState() {
if(_occasionalFields != null) {
_occasionalFields.ControlsViewState = null;
}
}
///
/// Indicates whether the current control's children have any saved view state
/// information. This property is read-only.
///
protected bool HasChildViewState {
get {
return ((_occasionalFields != null) &&
(_occasionalFields.ControlsViewState != null) &&
(_occasionalFields.ControlsViewState.Count > 0));
}
}
///
/// Sets initial focus on the control
///
public virtual void Focus() {
Page.SetFocus(this);
}
internal void LoadControlStateInternal(object savedStateObj) {
// Do not load the control state if it has been applied.
if (flags[controlStateApplied]) {
return;
}
flags.Set(controlStateApplied);
Pair savedState = (Pair)savedStateObj;
if (savedState == null) {
return;
}
Page page = Page;
if (page != null && !page.ShouldLoadControlState(this)) {
return;
}
// VSWhidbey160650: Only call LoadControlState with non null savedState
if (savedState.First != null) {
LoadControlState(savedState.First);
}
// VSWhidbey356804: Only call LoadAdapterControlState with non null savedState
if (_adapter == null || savedState.Second == null) {
return;
}
_adapter.LoadAdapterControlState(savedState.Second);
}
///
/// Load the control state, which is the essential state information needed even if view state is disabled.
///
protected internal virtual void LoadControlState(object savedState) {
}
///
/// Restores the view state information from a previous page
/// request that was saved by the Control.SavedState method.
///
protected virtual void LoadViewState(object savedState) {
if (savedState != null) {
ViewState.LoadViewState(savedState);
// Load values cached out of view state
object visible = ViewState["Visible"];
if (visible != null) {
if(!(bool)visible) {
flags.Set(invisible);
}
else {
flags.Clear(invisible);
}
flags.Set(visibleDirty);
}
}
}
internal void LoadViewStateRecursive(object savedState) {
// nothing to do if we have no state
if (savedState == null || flags[disableViewState])
return;
if (Page != null && Page.IsPostBack) {
object controlState = null;
object adapterState = null;
ArrayList childState = null;
Pair allSavedState = savedState as Pair;
if (allSavedState != null) {
controlState = allSavedState.First;
childState = (ArrayList)allSavedState.Second;
}
else {
Debug.Assert(savedState is Triplet);
Triplet t = (Triplet)savedState;
controlState = t.First;
adapterState = t.Second;
childState = (ArrayList)t.Third;
}
try {
if ((adapterState != null) && (_adapter != null)) {
_adapter.LoadAdapterViewState(adapterState);
}
if (controlState != null) {
LoadViewState(controlState);
}
if (childState != null) {
if (LoadViewStateByID) {
LoadChildViewStateByID(childState);
}
else {
LoadChildViewStateByIndex(childState);
}
}
}
catch (InvalidCastException) {
// catch all viewstate loading problems with casts. They are most likely changed control trees.
throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
}
catch (IndexOutOfRangeException) {
// catch all viewstate loading problems with indeces. They are most likely changed control trees.
throw new HttpException(SR.GetString(SR.Controls_Cant_Change_Between_Posts));
}
}
_controlState = ControlState.ViewStateLoaded;
}
internal void LoadChildViewStateByID(ArrayList childState) {
int childStateCount = childState.Count;
for (int i = 0; i < childStateCount; i += 2) {
// first element is index or ID of control with state and the
// next element is state of the control
string controlId = (string)childState[i];
object state = childState[i + 1];
Control childControl = FindControl(controlId);
if (childControl != null) {
childControl.LoadViewStateRecursive(state);
}
else {
// couldn't find a control for this state blob, save it for later
EnsureOccasionalFields();
if (_occasionalFields.ControlsViewState == null) {
_occasionalFields.ControlsViewState = new Hashtable();
}
_occasionalFields.ControlsViewState[controlId] = state;
}
}
}
internal void LoadChildViewStateByIndex(ArrayList childState) {
ControlCollection ctrlColl = Controls;
int ctrlCount = ctrlColl.Count;
int childStateCount = childState.Count;
for (int i = 0; i < childStateCount; i += 2) {
// first element is index of control with state and the
// next element is state of the control
int controlIndex = (int)childState[i];
object state = childState[i + 1];
if (controlIndex < ctrlCount) {
// we have a control for this state blob
ctrlColl[controlIndex].LoadViewStateRecursive(state);
}
else {
// couldn't find a control for this state blob, save it for later
EnsureOccasionalFields();
if (_occasionalFields.ControlsViewState == null) {
_occasionalFields.ControlsViewState = new Hashtable();
}
_occasionalFields.ControlsViewState[controlIndex] = state;
}
}
}
///
/// Figure out if a path is physical or virtual. This is useful because a number of our controls
/// accept either type of path for the same attribute.
///
internal void ResolvePhysicalOrVirtualPath(string path, out VirtualPath virtualPath, out string physicalPath) {
if (System.Web.Util.UrlPath.IsAbsolutePhysicalPath(path)) {
physicalPath = path;
virtualPath = null;
}
else {
physicalPath = null;
// It could be relative, so resolve it
virtualPath = TemplateControlVirtualDirectory.Combine(VirtualPath.Create(path));
}
}
///
///
/// This function takes a virtual path, that is a relative or root relative URL without a protocol.
/// It returns the mapped physcial file name relative to the template source. It throws an exception if
/// there is insufficient security access to read or investigate the mapped result. This should be used
/// by controls that can read files and live in fully trusted DLLs such as System.Web.dll to prevent
/// security issues. The exception thrown does not give away information about the mapping. For absolute
/// physical paths, this function checks permission
///
///
protected internal string MapPathSecure(string virtualPath) {
if (String.IsNullOrEmpty(virtualPath)) {
throw new ArgumentNullException("virtualPath", SR.GetString(SR.VirtualPath_Length_Zero));
}
string physicalPath;
VirtualPath virtualPathObject;
ResolvePhysicalOrVirtualPath(virtualPath, out virtualPathObject, out physicalPath);
if (physicalPath == null) {
physicalPath = virtualPathObject.MapPathInternal(TemplateControlVirtualDirectory,
true /*allowCrossAppMapping*/);
}
// Security check
HttpRuntime.CheckFilePermission(physicalPath);
return physicalPath;
}
///
///
/// This function takes a virtual path, that is a relative or root relative URL without a protocol.
/// It can also take a physical path, either local (c:\) or UNC.
/// It returns a stream used to read to contents of the file. It throws an exception if
/// there is insufficient security access to read or investigate the mapped result. This should be used
/// by controls that can read files and live in fully trusted DLLs such as System.Web.dll to prevent
/// security issues. The exception thrown does not give away information about the mapping. For absolute
/// physical paths, this function checks permission
///
///
protected internal Stream OpenFile(string path) {
string physicalPath = null;
VirtualFile vfile = null;
// Need to Trim it since MapPath no longer allows trailing space (VSWhidbey 441210)
path = path.Trim();
if (UrlPath.IsAbsolutePhysicalPath(path)) {
// Absolute physical path
physicalPath = path;
}
else {
vfile = HostingEnvironment.VirtualPathProvider.GetFile(path);
MapPathBasedVirtualFile mapPathVFile = vfile as MapPathBasedVirtualFile;
if (mapPathVFile != null) {
physicalPath = mapPathVFile.PhysicalPath;
}
}
// If we got a physical path, make sure the user has access to it
if (physicalPath != null) {
HttpRuntime.CheckFilePermission(physicalPath);
}
if (vfile != null) {
return vfile.Open();
}
else {
return new FileStream(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
}
///
/// Open a stream from either a virtual or physical path, and if possible get a CacheDependency
/// for the resulting Stream.
///
internal Stream OpenFileAndGetDependency(VirtualPath virtualPath, string physicalPath, out CacheDependency dependency) {
// Only one of the paths should be non-null
Debug.Assert((virtualPath == null) != (physicalPath == null));
// If we got a virtual path, and we're using the default VPP, call MapPath
if (physicalPath == null && HostingEnvironment.UsingMapPathBasedVirtualPathProvider) {
physicalPath = virtualPath.MapPathInternal(TemplateControlVirtualDirectory,
true /*allowCrossAppMapping*/);
}
Stream stream;
if (physicalPath != null) {
// Security check
HttpRuntime.CheckFilePermission(physicalPath);
// Work directly with the physical file, bypassing the VPP
stream = new FileStream(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
dependency = new CacheDependency(0, physicalPath);
}
else {
// It's non file system based, so go though the VirtualPathProvider
stream = virtualPath.OpenFile();
dependency = VirtualPathProvider.GetCacheDependency(virtualPath);
}
return stream;
}
///
/// Raises the
/// event. This notifies the control that it should perform any work that needs to
/// occur for each page request.
///
protected internal virtual void OnLoad(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventLoad] as EventHandler;
if(handler != null) {
handler(this, e);
}
}
}
internal virtual void LoadRecursive() {
// Only make the actual call if it hasn't already happened (ASURT 111303)
if (_controlState < ControlState.Loaded) {
if(_adapter != null) {
_adapter.OnLoad(EventArgs.Empty);
}
else {
OnLoad(EventArgs.Empty);
}
}
// Call Load on all our children
if (_occasionalFields != null && _occasionalFields.Controls != null) {
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
_occasionalFields.Controls[i].LoadRecursive();
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
if (_controlState < ControlState.Loaded)
_controlState = ControlState.Loaded;
}
///
/// Raises the event. This method uses event arguments
/// to pass the event data to the control.
///
protected internal virtual void OnPreRender(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventPreRender] as EventHandler;
if (handler != null) {
handler(this, e);
}
}
}
internal virtual void PreRenderRecursiveInternal() {
// Call Visible property and cache value in !flags[invisible] to allow Visible to be overridden.
// This avoids unnecessary virtual property calls in SaveViewState and Render.
bool visible = Visible;
if(!visible) {
flags.Set(invisible);
}
else {
flags.Clear(invisible);
EnsureChildControls();
if(_adapter != null) {
_adapter.OnPreRender(EventArgs.Empty);
}
else {
OnPreRender(EventArgs.Empty);
}
if (_occasionalFields != null && _occasionalFields.Controls != null) {
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i=0; i < controlCount; i++) {
_occasionalFields.Controls[i].PreRenderRecursiveInternal();
}
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
}
_controlState = ControlState.PreRendered;
}
internal int EstimateStateSize(object state) {
if(state == null) {
return 0;
}
return Util.SerializeWithAssert(new ObjectStateFormatter(), state).Length;
}
/*
* Walk the tree and fill in profile information
*/
///
///
/// Gathers information about the control and delivers it to the
/// property to be displayed when tracing is enabled for the page.
///
protected void BuildProfileTree(string parentId, bool calcViewState) {
// estimate the viewstate size.
calcViewState = calcViewState && (!flags[disableViewState]);
int viewstatesize;
if (calcViewState)
viewstatesize = EstimateStateSize(SaveViewState());
else
viewstatesize = 0;
int controlstatesize = 0;
if(Page != null && Page._registeredControlsRequiringControlState != null && Page._registeredControlsRequiringControlState.Contains(this)) {
controlstatesize = EstimateStateSize(SaveControlStateInternal());
}
// give it all to the profiler
Page.Trace.AddNewControl(UniqueID, parentId, this.GetType().FullName, viewstatesize, controlstatesize);
if (_occasionalFields != null && _occasionalFields.Controls != null) {
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++) {
_occasionalFields.Controls[i].BuildProfileTree(UniqueID, calcViewState);
}
}
}
internal object SaveControlStateInternal() {
object controlState = SaveControlState();
object adapterControlState = null;
if (_adapter != null) {
adapterControlState = _adapter.SaveAdapterControlState();
}
if (controlState != null || adapterControlState != null) {
return new Pair(controlState, adapterControlState);
}
return null;
}
///
/// Save the control state, which is the essential state information needed even if view state is disabled.
///
protected internal virtual object SaveControlState() {
return null;
}
// Save modified state the control would like restored on the postback.
// Return null if there is no state to save.
///
///
/// Saves view state for use with a later
/// request.
///
///
protected virtual object SaveViewState() {
// Save values cached out of view state
if (flags[visibleDirty]) {
ViewState["Visible"] = !flags[invisible];
}
if (_viewState != null)
return _viewState.SaveViewState();
return null;
}
// Answer any state this control or its descendants want to save on freeze.
// The format for saving is Triplet(myState, ArrayList childIDs, ArrayList childStates),
// where myState or childStates and childIDs may be null.
internal object SaveViewStateRecursive() {
if (flags[disableViewState])
return null;
object adapterState = null;
if (_adapter != null) {
adapterState = _adapter.SaveAdapterViewState();
}
object controlSavedState = SaveViewState();
ArrayList childStates = null;
if (HasControls()) {
ControlCollection occasionalFieldControls = _occasionalFields.Controls;
int occasionalFieldControlCount = occasionalFieldControls.Count;
bool useId = LoadViewStateByID;
for (int i = 0; i < occasionalFieldControlCount; i++) {
Control child = occasionalFieldControls[i];
object childState = child.SaveViewStateRecursive();
if (childState != null) {
if (childStates == null) {
childStates = new ArrayList(occasionalFieldControlCount);
}
if (useId) {
child.EnsureID();
childStates.Add(child.ID);
}
else {
childStates.Add(i);
}
childStates.Add(childState);
}
}
}
if (_adapter != null) {
if ((controlSavedState != null) || (adapterState != null) || (childStates != null)) {
return new Triplet(controlSavedState, adapterState, childStates);
}
}
else {
if ((controlSavedState != null) || (childStates != null)) {
return new Pair(controlSavedState, childStates);
}
}
return null;
}
///
/// Outputs control content to a provided HTMLTextWriter
/// output stream.
///
protected internal virtual void Render(HtmlTextWriter writer) {
RenderChildren(writer);
}
internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children) {
// If we have a delegate, use it for the rendering.
// This happens when there is some ASP code. See also Whidbey 33012.
if(RareFields != null && RareFields.RenderMethod != null ) {
writer.BeginRender();
RareFields.RenderMethod(writer, this);
writer.EndRender();
return;
}
if (children != null) {
foreach (Control child in children) {
child.RenderControl(writer);
}
}
}
protected internal virtual void RenderChildren(HtmlTextWriter writer) {
ICollection children = (_occasionalFields == null) ? null : _occasionalFields.Controls;
RenderChildrenInternal(writer, children);
}
///
/// [To be supplied.]
///
public virtual void RenderControl(HtmlTextWriter writer) {
//use the Adapter property to ensure it is resolved
RenderControl(writer, Adapter);
}
///
/// Used for MobilePage implementation.
///
protected void RenderControl(HtmlTextWriter writer, ControlAdapter adapter) {
if (!flags[invisible] && !flags[notVisibleOnPage]) {
HttpContext context = (Page == null) ? null : Page._context;
if (context != null && context.TraceIsEnabled) {
int presize = context.Response.GetBufferedLength();
RenderControlInternal(writer, adapter);
int postsize = context.Response.GetBufferedLength();
context.Trace.AddControlSize(UniqueID, postsize - presize);
}
else {
RenderControlInternal(writer, adapter);
}
}
}
private void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) {
if (adapter != null) {
//
adapter.BeginRender(writer);
adapter.Render(writer);
adapter.EndRender(writer);
}
else {
Render(writer);
}
}
///
/// [To be supplied.]
///
protected internal virtual void OnUnload(EventArgs e) {
if(HasEvents()) {
EventHandler handler = _occasionalFields.Events[EventUnload] as EventHandler;
if (handler != null) {
handler(this, e);
}
}
}
///
/// Enables a control to perform final cleanup.
///
public virtual void Dispose() {
IContainer container = null;
if (Site != null) {
container = (IContainer)Site.GetService(typeof(IContainer));
if (container != null) {
container.Remove(this);
EventHandler disp = Events[EventDisposed] as EventHandler;
if (disp != null)
disp(this, EventArgs.Empty);
}
}
if (_occasionalFields != null) {
_occasionalFields.Dispose();
//do not null out for backwards compat, VSWhidbey 475940
//_occasionalFields = null;
}
}
internal virtual void UnloadRecursive(bool dispose) {
Page page = Page;
if (page != null && page.RequiresControlState(this)) {
page.UnregisterRequiresControlState(this);
RareFieldsEnsured.RequiredControlState = true;
}
// Remove the generated ID so it will be assigned a different ID next time.
if (flags[useGeneratedID]) {
_id = null;
flags.Clear(useGeneratedID);
}
if (_occasionalFields != null && _occasionalFields.Controls != null) {
string oldmsg = _occasionalFields.Controls.SetCollectionReadOnly(SR.Parent_collections_readonly);
int controlCount = _occasionalFields.Controls.Count;
for (int i = 0; i < controlCount; i++)
_occasionalFields.Controls[i].UnloadRecursive(dispose);
_occasionalFields.Controls.SetCollectionReadOnly(oldmsg);
}
if(_adapter != null) {
_adapter.OnUnload(EventArgs.Empty);
}
else {
OnUnload(EventArgs.Empty);
}
//
if (dispose)
Dispose();
// VSWhidbey 244999: Everett behavior doesn't reset the control state.
// But for control which requires its OnInit method to be called again
// to properly initialize when the control is removed and added back
// to Page's control tree, the control can override IsReloadable
// to true so the control state is reset. e.g. Validator, see bug
if (IsReloadable) {
_controlState = ControlState.Constructed;
}
}
///
/// Assigns an sources of the event and its information up the page control
/// hierarchy until they reach the top of the control tree.
///
protected void RaiseBubbleEvent(object source, EventArgs args) {
Control currentTarget = Parent;
while (currentTarget != null) {
if (currentTarget.OnBubbleEvent(source, args)) {
return;
}
currentTarget = currentTarget.Parent;
}
}
///
/// Determines whether the event for the control should be passed up the page's
/// control hierarchy.
///
protected virtual bool OnBubbleEvent(object source, EventArgs args) {
return false;
}
// Members related to being a container
///
/// Gets a ControlCollection object that represents the child controls for a specified control in the
/// UI hierarchy.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_Controls)
]
public virtual ControlCollection Controls {
get {
if (_occasionalFields == null || _occasionalFields.Controls == null) {
EnsureOccasionalFields();
_occasionalFields.Controls = CreateControlCollection();
}
return _occasionalFields.Controls;
}
}
///
/// Indicates a dictionary of state information that allows you to save and restore
/// the state of a control across multiple requests for the same page.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.Control_State)
]
protected virtual StateBag ViewState {
get {
if (_viewState != null) { // create a StateBag on demand; WebControl makes its case sensitive
return _viewState;
}
_viewState = new StateBag(ViewStateIgnoresCase);
if (IsTrackingViewState)
_viewState.TrackViewState();
return _viewState;
}
}
// fast enough that we cam always use it.
///
/// Indicates whether the object is case-insensitive.
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
]
protected virtual bool ViewStateIgnoresCase {
get {
return false;
}
}
///
///
protected internal virtual void AddedControl(Control control, int index) {
if (control.OwnerControl != null) {
throw new InvalidOperationException(SR.GetString(SR.Substitution_NotAllowed));
}
if (control._parent != null) {
control._parent.Controls.Remove(control);
}
control._parent = this;
control._page = Page;
control.flags.Clear(designModeChecked);
// We only add to naming container if it is available. Otherwise, it will be pushed through
// during InitRecursive
Control namingContainer = flags[isNamingContainer] ? this : _namingContainer;
if (namingContainer != null) {
control.UpdateNamingContainer(namingContainer);
if (control._id == null && !control.flags[idNotRequired]) {
// this will also dirty the name table in the naming container
control.GenerateAutomaticID();
}
else if (control._id != null || (control._occasionalFields != null && control._occasionalFields.Controls != null)) {
// If the control has and ID, or has children (which *may* themselves
// have ID's), we need to dirty the name table (ASURT 100557)
namingContainer.DirtyNameTable();
}
}
/*
* The following is for times when AddChild is called after CreateChildControls. This
* allows users to add children at any time in the creation process without having
* to understand the underlying machinery.
* Note that if page is null, it means we haven't been attached to a container ourselves.
* If this is true, when we are, our children will be recursively set up.
*/
if (_controlState >= ControlState.ChildrenInitialized) {
Debug.Assert(namingContainer != null);
control.InitRecursive(namingContainer);
// VSWhidbey 396372: We need to reregister the control state if the control is reparented because the control
// is unregistered during unload, but its already been inited once, so it will not get its Init called again
// which is where most controls call RegisterRequiresControlState
if (control._controlState >= ControlState.Initialized &&
control.RareFields != null &&
control.RareFields.RequiredControlState) {
Page.RegisterRequiresControlState(control);
}
if (_controlState >= ControlState.ViewStateLoaded) {
object viewState = null;
if(_occasionalFields != null && _occasionalFields.ControlsViewState != null) {
viewState = _occasionalFields.ControlsViewState[index];
// This solution takes the conservative approach that once viewstate has been
// applied to a child control, it is thrown away. This eliminates inadvertently
// setting viewstate on the wrong control, which can occur in scenarios where
// the child control collection is being manipulated via code. Probably need
// to provide a feature where programmer can control whether to reapply viewstate
// or not.
if (LoadViewStateByID) {
control.EnsureID();
viewState = _occasionalFields.ControlsViewState[control.ID];
_occasionalFields.ControlsViewState.Remove(control.ID);
}
else {
viewState = _occasionalFields.ControlsViewState[index];
_occasionalFields.ControlsViewState.Remove(index);
}
}
control.LoadViewStateRecursive(viewState);
if (_controlState >= ControlState.Loaded) {
control.LoadRecursive();
if (_controlState >= ControlState.PreRendered)
control.PreRenderRecursiveInternal();
}
}
}
}
///
/// [To be supplied.]
///
protected virtual ControlCollection CreateControlCollection() {
return new ControlCollection(this);
}
///
///
/// Notifies any controls that use composition-based implementation to create any
/// child controls they contain in preperation for postback or rendering.
///
///
protected internal virtual void CreateChildControls() {
}
///
/// Indicates whether the control's child controls have been created.
///
protected bool ChildControlsCreated {
get {
return flags[controlsCreated];
}
set {
if (!value && flags[controlsCreated]) {
Controls.Clear();
}
if(value) {
flags.Set(controlsCreated);
}
else {
flags.Clear(controlsCreated);
}
}
}
///
/// Make a URL absolute using the AppRelativeTemplateSourceDirectory. The returned URL is for
/// client use, and will contain the session cookie if appropriate.
///
public string ResolveUrl(string relativeUrl) {
if (relativeUrl == null) {
throw new ArgumentNullException("relativeUrl");
}
// check if its empty or already absolute
if ((relativeUrl.Length == 0) || (UrlPath.IsRelativeUrl(relativeUrl) == false)) {
return relativeUrl;
}
string baseUrl = AppRelativeTemplateSourceDirectory;
if (String.IsNullOrEmpty(baseUrl)) {
return relativeUrl;
}
// first make it absolute
string url = UrlPath.Combine(baseUrl, relativeUrl);
// include the session cookie if available (ASURT 47658)
// As a side effect, this will change an app relative path (~/...) to app absolute
return Context.Response.ApplyAppPathModifier(url);
}
///
/// Return a URL that is suitable for use on the client.
/// If the URL is absolute, return it unchanged. If it is relative, turn it into a
/// relative URL that is correct from the point of view of the current request path
/// (which is what the browser uses for resolution).
///
public string ResolveClientUrl(string relativeUrl) {
if (DesignMode && Page != null && Page.Site != null) {
IUrlResolutionService resolutionService = (IUrlResolutionService)Page.Site.GetService(typeof(IUrlResolutionService));
if (resolutionService != null) {
return resolutionService.ResolveClientUrl(relativeUrl);
}
}
if (relativeUrl == null) {
throw new ArgumentNullException("relativeUrl");
}
// Get the app absolute TemplateSourceDirectory (not app relative)
string tplSourceDir = VirtualPath.GetVirtualPathString(TemplateControlVirtualDirectory);
if (String.IsNullOrEmpty(tplSourceDir))
return relativeUrl;
string baseRequestDir = Context.Request.ClientBaseDir.VirtualPathString;
// If the path is app relative (~/...), we cannot take shortcuts, since
// the ~ is meaningless on the client, and must be resolved
if (!UrlPath.IsAppRelativePath(relativeUrl)) {
// If the template source directory is the same as the directory of the request,
// we don't need to do any adjustments to the input path
if (StringUtil.EqualsIgnoreCase(baseRequestDir, tplSourceDir))
return relativeUrl;
// check if it's empty or absolute
if ((relativeUrl.Length == 0) || (!UrlPath.IsRelativeUrl(relativeUrl))) {
return relativeUrl;
}
}
// first make it absolute
string url = UrlPath.Combine(tplSourceDir, relativeUrl);
// Make sure the path ends with a slash before calling MakeRelative
baseRequestDir = UrlPath.AppendSlashToPathIfNeeded(baseRequestDir);
// Now, make it relative to the current request, so that the client will
// compute the correct path
return HttpUtility.UrlPathEncode(UrlPath.MakeRelative(baseRequestDir, url));
}
internal void DirtyNameTable() {
Debug.Assert(this is INamingContainer);
if(_occasionalFields != null) {
_occasionalFields.NamedControls = null;
}
}
private void EnsureNamedControlsTable() {
Debug.Assert(this is INamingContainer);
Debug.Assert(HasControls());
Debug.Assert(_occasionalFields != null);
Debug.Assert(_occasionalFields.NamedControls == null);
_occasionalFields.NamedControls = new HybridDictionary(/*initialSize*/ _occasionalFields.NamedControlsID, /*caseInsensitive*/ true);
FillNamedControlsTable(this, _occasionalFields.Controls);
}
private void FillNamedControlsTable(Control namingContainer, ControlCollection controls) {
Debug.Assert(namingContainer._occasionalFields != null);
Debug.Assert(namingContainer._occasionalFields.NamedControls != null);
Debug.Assert((controls != null) && (controls.Count != 0));
int controlCount = controls.Count;
for (int i=0; i < controlCount; i++) {
Control control = controls[i];
if (control._id != null) {
#if DEBUG
if (control._namingContainer != null) {
Debug.Assert(control._namingContainer == namingContainer);
}
#endif // DEBUG
try {
namingContainer.EnsureOccasionalFields();
namingContainer._occasionalFields.NamedControls.Add(control._id, control);
}
catch {
throw new HttpException(SR.GetString(SR.Duplicate_id_used, control._id, "FindControl"));
}
}
if (control.HasControls() && (control.flags[isNamingContainer] == false)) {
FillNamedControlsTable(namingContainer, control.Controls);
}
}
}
///
/// Searches the current naming container for a control with
/// the specified .
///
public virtual Control FindControl(String id) {
return FindControl(id, 0);
}
///
///
/// Searches the current naming container for a control with the specified
/// and an offset to aid in the
/// search.
///
protected virtual Control FindControl(String id, int pathOffset) {
string childID;
EnsureChildControls();
// If we're not the naming container, let it do the job
if (!(flags[isNamingContainer])) {
Control namingContainer = NamingContainer;
if (namingContainer != null) {
return namingContainer.FindControl(id, pathOffset);
}
return null;
}
// No registered control, demand create the named controls table
//call HasControls ensuress _occasionalFields != null
if(HasControls() && _occasionalFields.NamedControls == null) {
EnsureNamedControlsTable();
}
if (_occasionalFields == null || _occasionalFields.NamedControls == null) {
return null;
}
// Need to support ':' for V1 backward compatibility.
char[] findControlSeparators = { ID_SEPARATOR, LEGACY_ID_SEPARATOR };
// Is it a hierarchical name?
int newPathOffset = id.IndexOfAny(findControlSeparators, pathOffset);
// If not, handle it here
if (newPathOffset == -1) {
childID = id.Substring(pathOffset);
return _occasionalFields.NamedControls[childID] as Control;
}
// Get the name of the child, and try to locate it
childID = id.Substring(pathOffset, newPathOffset - pathOffset);
Control child = _occasionalFields.NamedControls[childID] as Control;
// Child doesn't exist: fail
if (child == null)
return null;
return child.FindControl(id, newPathOffset + 1);
}
/*
* Called when the controls of a naming container are cleared.
*/
internal void ClearNamingContainer() {
Debug.Assert(this is INamingContainer);
EnsureOccasionalFields();
_occasionalFields.NamedControlsID = 0;
DirtyNameTable();
}
///
///
///
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
protected virtual IDictionary GetDesignModeState() {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.DesignModeState == null) {
rareFields.DesignModeState = new HybridDictionary();
}
return rareFields.DesignModeState;
}
///
/// Determines if the current control contains any child
/// controls. Since this method simply deteremines if any child controls exist at
/// all, it can enhance performance by avoiding a call to the Count property,
/// inherited from the class, on the
/// property.
///
public virtual bool HasControls() {
return _occasionalFields != null && _occasionalFields.Controls != null && _occasionalFields.Controls.Count > 0;
}
/*
* Check if a Control either has children or has a compiled render method.
* This is to address issues like ASURT 94127
*/
internal bool HasRenderingData() {
return HasControls() || HasRenderDelegate();
}
/*
* Check if a Control either has children or has a compiled render method.
* This is to address issues like ASURT 94127
*/
internal bool HasRenderDelegate() {
if(RareFields != null) {
return (RareFields.RenderMethod != null );
}
return false;
}
/*
* Returns true if the container contains just a static string, i.e.,
* when the Controls collection has a single LiteralControl.
*/
///
/// Determines if the container holds literal content only.
/// When this method returns
/// , the container collection only holds a single literal control. The
/// content is then passed to the requesting browser as HTML.
///
protected bool IsLiteralContent() {
return (_occasionalFields != null && _occasionalFields.Controls != null) && (_occasionalFields.Controls.Count == 1) &&
((_occasionalFields.Controls[0] is LiteralControl));
}
///
/// Determines if view state changes to the
///
/// are being saved.
///
protected bool IsTrackingViewState {
get {
return flags[marked];
}
}
///
/// Turns on tracking of view state changes to the control
/// so that they can be stored in the
/// object.
///
protected virtual void TrackViewState() {
if (_viewState != null)
_viewState.TrackViewState();
flags.Set(marked);
}
///
/// Checks that the control contains child controls; if it does not, it creates
/// them. This includes any literal content being parsed as a
/// object.
///
protected virtual void EnsureChildControls() {
if (!ChildControlsCreated && !flags[creatingControls]) {
flags.Set(creatingControls);
try {
ResolveAdapter();
if(_adapter != null) {
_adapter.CreateChildControls();
}
else {
CreateChildControls();
}
// Only set ChildControlsCreated = true if CreateChildControls() did not throw
// an exception (VSWhidbey 465798).
ChildControlsCreated = true;
}
finally {
flags.Clear(creatingControls);
}
}
}
///
/// Used internally to store a ControlBuilder reference for the control.
/// The builder will be used at design-time to help persist all the filtered properties
/// of the control.
///
internal void SetControlBuilder(ControlBuilder controlBuilder) {
RareFieldsEnsured.ControlBuilder = controlBuilder;
}
///
///
protected internal virtual void RemovedControl(Control control) {
if (control.OwnerControl != null) {
throw new InvalidOperationException(SR.GetString(SR.Substitution_NotAllowed));
}
if ((_namingContainer != null) && (control._id != null)) {
_namingContainer.DirtyNameTable();
}
// Controls may need to do their own cleanup.
control.UnloadRecursive(false);
control._parent = null;
control._page = null;
control._namingContainer = null;
// Don't reset _templateSourceVirtualDirectory on TemplateControl's, because
// the path is their own, not their parent. i.e. it doesn't change no matter
// where in the tree they end up.
if (!(control is TemplateControl))
control._templateSourceVirtualDirectory = null;
control._templateControl = null;
control.flags.Clear(mustRenderID);
control.ClearCachedUniqueIDRecursive();
}
internal void SetDesignMode() {
flags.Set(designMode);
flags.Set(designModeChecked);
}
///
///
///
protected virtual void SetDesignModeState(IDictionary data) {
}
// Set the delegate to the render method
///
///
/// Assigns any event handler delegates for the control to match the parameters
/// defined in the .
///
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void SetRenderMethodDelegate(RenderMethod renderMethod) {
RareFieldsEnsured.RenderMethod = renderMethod;
// Make the collection readonly if there are code blocks (ASURT 78810)
Controls.SetCollectionReadOnly(SR.Collection_readonly_Codeblocks);
}
///
///
/// Returns whether the control contains any data binding logic. This method is
/// only accessed by RAD designers.
///
bool IDataBindingsAccessor.HasDataBindings {
get {
return ((RareFields != null) && (RareFields.DataBindings != null) && (RareFields.DataBindings.Count != 0));
}
}
///
///
/// Indicates a collection of all data bindings on the control. This property is
/// read-only.
///
DataBindingCollection IDataBindingsAccessor.DataBindings {
get {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.DataBindings == null) {
rareFields.DataBindings = new DataBindingCollection();
}
return rareFields.DataBindings;
}
}
// IParserAccessor interface
// A sub-object tag was parsed by the parser; add it to this control.
///
///
/// Notifies the control that an element, XML or HTML, was parsed, and adds it to
/// the control.
///
void IParserAccessor.AddParsedSubObject(object obj) {
AddParsedSubObject(obj);
}
internal string SpacerImageUrl {
get {
EnsureOccasionalFields();
if (_occasionalFields.SpacerImageUrl == null) {
_occasionalFields.SpacerImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(WebControl), "Spacer.gif");
}
return _occasionalFields.SpacerImageUrl;
}
}
private Control OwnerControl {
get {
if (RareFields == null) {
return null;
}
return RareFields.OwnerControl;
}
set {
RareFieldsEnsured.OwnerControl = value;
}
}
internal IPostBackDataHandler PostBackDataHandler {
get {
IPostBackDataHandler pbdh = _adapter as IPostBackDataHandler;
if(pbdh != null)
return pbdh;
pbdh = this as IPostBackDataHandler;
return pbdh;
}
}
internal IPostBackEventHandler PostBackEventHandler {
get {
IPostBackEventHandler pbeh = _adapter as IPostBackEventHandler;
if(pbeh != null)
return pbeh;
pbeh = this as IPostBackEventHandler;
return pbeh;
}
}
#if ORCAS
internal bool NotVisibleOnPage {
get {
return flags[notVisibleOnPage];
}
set {
if(value) {
flags.Set(notVisibleOnPage);
}
else {
flags.Clear(notVisibleOnPage);
}
}
}
internal int VirtualStartPage {
get {
return RareFields != null ? RareFields.VirtualStartPage : -1;
}
set {
RareFieldsEnsured.VirtualStartPage = value;
}
}
internal int VirtualEndPage {
get {
return RareFields != null ? RareFields.VirtualEndPage : -1;
}
set {
RareFieldsEnsured.VirtualEndPage = value;
}
}
#endif
#region IControlDesignerAccessor implementation
///
IDictionary IControlDesignerAccessor.UserData {
get {
ControlRareFields rareFields = RareFieldsEnsured;
if (rareFields.ControlDesignerAccessorUserData == null) {
rareFields.ControlDesignerAccessorUserData = new HybridDictionary();
}
return rareFields.ControlDesignerAccessorUserData;
}
}
///
///
///
IDictionary IControlDesignerAccessor.GetDesignModeState() {
return GetDesignModeState();
}
///
///
///
void IControlDesignerAccessor.SetDesignModeState(IDictionary data) {
SetDesignModeState(data);
}
void IControlDesignerAccessor.SetOwnerControl(Control owner) {
if (owner == this) {
throw new ArgumentException(SR.GetString(SR.Control_CannotOwnSelf), "owner");
}
OwnerControl = owner;
_parent = owner.Parent;
_page = owner.Page;
}
#endregion
#region IControlBuilderAccessor implementation
///
///
/// A reference to the ControlBuilder that was used to construct this control (if there was one)
///
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
ControlBuilder IControlBuilderAccessor.ControlBuilder {
get {
return RareFields != null ? RareFields.ControlBuilder : null;
}
}
#endregion IControlBuilderAccessor implementation
#region IExpressionsAccessor
///
bool IExpressionsAccessor.HasExpressions {
get {
if (RareFields == null) {
return false;
}
ExpressionBindingCollection expressions = RareFields.ExpressionBindings;
return ((expressions != null) && (expressions.Count > 0));
}
}
///
ExpressionBindingCollection IExpressionsAccessor.Expressions {
get {
ExpressionBindingCollection expressions = RareFieldsEnsured.ExpressionBindings;
if (expressions == null) {
expressions = new ExpressionBindingCollection();
RareFields.ExpressionBindings = expressions;
}
return expressions;
}
}
#endregion
private sealed class ControlRareFields : IDisposable {
internal ControlRareFields() {
}
public ISite Site;
public RenderMethod RenderMethod;
// Reference to the templateControl that hosts this control.
#if ORCAS
public int VirtualStartPage = -1;
public int VirtualEndPage = -1;
public ContentPager ContentPager;
#endif
// Reference to the ControlBuilder used to build this control
public ControlBuilder ControlBuilder;
public DataBindingCollection DataBindings;
public Control OwnerControl;
public ExpressionBindingCollection ExpressionBindings;
public bool RequiredControlState = false;
// These fields are only used in the designer so we
// keep them here to prevent memory bloat at runtime
public IDictionary ControlDesignerAccessorUserData;
public IDictionary DesignModeState;
public void Dispose() {
//do not null out for backwards compat, VSWhidbey 475940
//Site = null;
//RenderMethod = null;
//DataBindings = null;
//OwnerControl = null;
//ExpressionBindings = null;
ControlBuilder = null;
if (OwnerControl != null)
{
OwnerControl.Dispose();
}
ControlDesignerAccessorUserData = null;
DesignModeState = null;
#if ORCAS
ContentPager = null;
#endif
}
}
private sealed class OccasionalFields : IDisposable {
internal OccasionalFields() {
}
public string SkinId;
// Events
public EventHandlerList Events;
public IDictionary ControlsViewState;
public ControlCollection Controls;
public int NamedControlsID;
// Only used if we are a naming container. It contains all the controls
// in the namespace.
public IDictionary NamedControls;
public ControlRareFields RareFields;
public String UniqueIDPrefix;
public string SpacerImageUrl;
public void Dispose() {
if (Events != null) {
Events.Dispose();
Events = null;
}
if (RareFields != null) {
RareFields.Dispose();
}
ControlsViewState = null;
//do not null out for backwards compat, VSWhidbey 475940
//Controls = null;
//NamedControls = null;
//UniqueIDPrefix = null;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataSourceProvider.cs
- XmlSchemaAppInfo.cs
- _NestedSingleAsyncResult.cs
- ExpressionConverter.cs
- ConstNode.cs
- CollectionViewProxy.cs
- EnvironmentPermission.cs
- DecimalFormatter.cs
- OleDbException.cs
- UIElementCollection.cs
- ScrollProperties.cs
- IISMapPath.cs
- WindowsStatic.cs
- EntityDataSourceDesigner.cs
- SrgsToken.cs
- BitmapFrame.cs
- Transform.cs
- TranslateTransform3D.cs
- DataGridBeginningEditEventArgs.cs
- AdapterUtil.cs
- RestHandlerFactory.cs
- FileLevelControlBuilderAttribute.cs
- AdCreatedEventArgs.cs
- HtmlToClrEventProxy.cs
- DataColumnCollection.cs
- HtmlInputImage.cs
- PipelineModuleStepContainer.cs
- MeasureItemEvent.cs
- Errors.cs
- Line.cs
- DataGridClipboardHelper.cs
- GlobalDataBindingHandler.cs
- PrtTicket_Public_Simple.cs
- RecognizeCompletedEventArgs.cs
- FormViewUpdatedEventArgs.cs
- ComponentEvent.cs
- SafeFileMapViewHandle.cs
- ToolboxBitmapAttribute.cs
- RepeaterItemEventArgs.cs
- ReachNamespaceInfo.cs
- AnimationLayer.cs
- entityreference_tresulttype.cs
- Claim.cs
- ParamArrayAttribute.cs
- AsyncSerializedWorker.cs
- ObjectParameterCollection.cs
- UriTemplateMatchException.cs
- AppDomainAttributes.cs
- DefaultMemberAttribute.cs
- UriPrefixTable.cs
- TypeUsageBuilder.cs
- StreamAsIStream.cs
- DbProviderSpecificTypePropertyAttribute.cs
- ColumnReorderedEventArgs.cs
- Input.cs
- DatePickerTextBox.cs
- LicenseManager.cs
- XmlBoundElement.cs
- StringWriter.cs
- X509Chain.cs
- TimestampInformation.cs
- PropertyPanel.cs
- SqlError.cs
- SelectionWordBreaker.cs
- TextTreeObjectNode.cs
- CompositeCollection.cs
- DataTemplateKey.cs
- SafeNativeMethodsMilCoreApi.cs
- XmlAnyElementAttribute.cs
- StyleXamlParser.cs
- GlobalItem.cs
- ApplicationHost.cs
- PropertyExpression.cs
- XmlHierarchicalDataSourceView.cs
- DataGridAutoFormat.cs
- CommandExpr.cs
- SystemIPAddressInformation.cs
- EnvironmentPermission.cs
- ResourceReferenceKeyNotFoundException.cs
- ToolStripDropDownItem.cs
- Attributes.cs
- EntityClientCacheEntry.cs
- AdPostCacheSubstitution.cs
- RelationshipEnd.cs
- AudienceUriMode.cs
- SmiConnection.cs
- TransformPattern.cs
- ContractListAdapter.cs
- FilteredXmlReader.cs
- X509Certificate2.cs
- TextRenderer.cs
- EventlogProvider.cs
- XamlToRtfWriter.cs
- BindingExpressionBase.cs
- GroupLabel.cs
- Int32Storage.cs
- _FtpDataStream.cs
- DocumentSchemaValidator.cs
- NewArray.cs
- FlagsAttribute.cs