📄 extendercontrolbase.cs
字号:
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Web.Script;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
[assembly: System.Web.UI.WebResource(AjaxControlToolkit.Constants.BaseScriptResourceName, "text/javascript")]
[assembly: ScriptResource(AjaxControlToolkit.Constants.BaseScriptResourceName, "AjaxControlToolkit.ScriptResources.ScriptResources.resources", "AjaxControlToolkit.Resources")]
namespace AjaxControlToolkit
{
/// <summary>
/// This is the main class for extenders. It has several main jobs:
///
/// 1) It performs the hookup between an Extender (server) control and the behavior it instantiates
/// 2) It manages interacting with the ScriptManager to get the right scripts loaded
/// 3) It adds some debugging features like ValidationScript and ScriptPath
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="C"></typeparam>
///
[ParseChildren(true)]
[PersistChildren(false)]
[ClientScriptResource(null, Constants.BaseScriptResourceName)]
[Themeable(true)]
public abstract class ExtenderControlBase : ExtenderControl, IControlResolver
{
private Dictionary<string, Control> _findControlHelperCache = new Dictionary<string, Control>();
private bool _renderingScript;
private bool _loadedClientStateValues;
// Make SkinID browsable since Themeable(true) is set for this class
[Browsable(true)]
public override string SkinID
{
get { return base.SkinID; }
set { base.SkinID = value; }
}
/// <summary>
/// Called when the ExtenderControlBase fails to locate a control referenced by a TargetControlID.
/// In this event, user code is given an opportunity to find the control.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", Justification = "Following ASP.NET AJAX pattern")]
public event ResolveControlEventHandler ResolveControlID;
/// <summary>
/// For debugging - set this to false if you don't want people being able to specify a script path
/// to redirect the script loading for the extender.
/// </summary>
protected virtual bool AllowScriptPath
{
get
{
return true;
}
}
/// <summary>
/// The type of the client component - e.g. "ConfirmButtonBehavior"
/// </summary>
protected virtual string ClientControlType
{
get
{
ClientScriptResourceAttribute attr = (ClientScriptResourceAttribute)TypeDescriptor.GetAttributes(this)[typeof(ClientScriptResourceAttribute)];
return attr.ComponentType;
}
}
private bool _isDisposed;
public bool Enabled {
get {
if (_isDisposed)
return false;
return GetPropertyValue("Enabled", true);
}
set {
SetPropertyValue("Enabled", value);
}
}
/// <summary>
/// Property for determining if script rendering is currently underway. This is used to determine
/// if Script or markup is being rendered.
/// </summary>
protected bool IsRenderingScript
{
get
{
return _renderingScript;
}
}
/// <summary>
/// For debugging - setting this causes the extender to load the specified script instead of the one out of the resources. This
/// lets you set breakpoints and modify the script without rebuilding, etc.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", Justification = "Assembly is not localized")]
public string ScriptPath
{
get
{
return GetPropertyValue("ScriptPath", (string)null);
}
set
{
if (!AllowScriptPath)
{
throw new InvalidOperationException("This class does not allow setting of ScriptPath.");
}
SetPropertyValue("ScriptPath", value);
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Using correct base class implementation and simply setting a flag on the way")]
public override void Dispose()
{
this._isDisposed = true;
base.Dispose();
GC.SuppressFinalize(this);
}
/// <summary>
/// Walks the various script types and prepares to notify the ScriptManager to load them.
/// 1) Required scripts such as ASP.NET AJAX Scripts or other components
/// 2) Scripts for this Extender/Behavior
/// </summary>
internal IEnumerable<ScriptReference> EnsureScripts(/*ScriptManager scriptManager*/) {
List<ScriptReference> scriptRefs = new List<ScriptReference>();
scriptRefs.AddRange(ScriptObjectBuilder.GetScriptReferences(GetType(), (null != ScriptPath)));
string scriptPath = ScriptPath;
if (!string.IsNullOrEmpty(scriptPath))
{
scriptRefs.Add(new ScriptReference(scriptPath));
}
return scriptRefs;
}
/// <summary>
/// This helper automates locating a control by ID.
///
/// It calls FindControl on the NamingContainer, then the Page. If that fails,
/// it fires the resolve event.
/// </summary>
/// <param name="id">The ID of the control to find</param>
/// <param name="props">The TargetProperties class associated with that control</param>
/// <returns></returns>
protected Control FindControlHelper(string id)
{
Control c = null;
if (_findControlHelperCache.ContainsKey(id))
{
c = _findControlHelperCache[id];
}
else
{
c = base.FindControl(id); // Use "base." to avoid calling self in an infinite loop
Control nc = NamingContainer;
while ((null == c) && (null != nc))
{
c = nc.FindControl(id);
nc = nc.NamingContainer;
}
if (null == c)
{
// Note: props MAY be null, but we're firing the event anyway to let the user
// do the best they can
ResolveControlEventArgs args = new ResolveControlEventArgs(id);
OnResolveControlID(args);
c = args.Control;
}
if (null != c)
{
_findControlHelperCache[id] = c;
}
}
return c;
}
public override Control FindControl(string id)
{
// Use FindControlHelper so that more complete searching and OnResolveControlID will be used
return FindControlHelper(id);
}
protected Control TargetControl
{
get
{
return FindControlHelper(TargetControlID);
}
}
[ExtenderControlProperty()]
[ClientPropertyName("id")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", Justification = "Following ASP.NET AJAX pattern")]
public string BehaviorID
{
get
{
string id = GetPropertyValue("BehaviorID", "");
return (string.IsNullOrEmpty(id) ? ClientID : id);
}
set
{
SetPropertyValue("BehaviorID", value);
}
}
/// <summary>
/// Gets the ClientID for a given control, based on it's ID
/// </summary>
/// <param name="controlId">The ID of the Control</param>
/// <param name="props">The associated TargetProperties object</param>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", Justification = "Following ASP.NET AJAX pattern")]
protected string GetClientID(string controlId)
{
Control c = FindControlHelper(controlId);
if (c != null)
{
controlId = c.ClientID;
}
return controlId;
}
/// <summary>
/// Helper to generate a clientState ID
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
private string GetClientStateFieldID()
{
return string.Format(CultureInfo.InvariantCulture, "{0}_ClientState", ID);
}
/// <summary>
/// On Init we load target properties values and process data-binding handlers.
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
if (EnableClientState)
{
CreateClientStateField();
}
Page.PreLoad += new EventHandler(Page_PreLoad);
base.OnInit(e);
}
/// <summary>
/// Event handler for the Page.PreLoad event
/// </summary>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -