📄 extendercontrolbasedesigner.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.Globalization;
using System.Web.UI;
using System.Web.UI.Design;
using System.ComponentModel.Design;
namespace AjaxControlToolkit.Design
{
/// <summary>
/// The designer here has two main jobs:
///
/// 1) Modifying the properties of the TargetProperties objects to remove the "TargetControlID" property and add the Control converter.
/// We remove "TargetControlID" because the value will be hanging off of the target control's properties already so it's confusing/redundant.
/// 2) Modifying the name of the Extender property so it's user-configurable.
///
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2117:AptcaTypesShouldOnlyExtendAptcaBaseTypes", Justification="Security handled by base class")]
public partial class ExtenderControlBaseDesigner<T> :
ExtenderControlDesigner, IExtenderProvider
where T : ExtenderControlBase
{
// we keep track of the providers we've created.
//
ExtenderPropertyRenameDescProv _renameProvider;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "Call to AddAttributes can not be moved inline")]
static ExtenderControlBaseDesigner()
{
TypeDescriptor.AddAttributes(typeof(ExtenderControlBaseDesigner<T>), new ProvidePropertyAttribute("Extender", typeof(Control)));
}
public ExtenderControlBaseDesigner()
{
}
/// <summary>
/// Orcas implements their own extender designer features, so in that case we disable ours.
/// </summary>
private const int DisableDesignerFeaturesUnknown = 0;
private const int DisableDesignerFeaturesYes = 1;
private const int DisableDesignerFeaturesNo = 2;
private int _disableDesignerFeatures = DisableDesignerFeaturesUnknown;
private const string ExtenderControlDictionaryKey = "ExtenderControlFeaturesPresent";
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
protected bool DesignerFeaturesEnabled
{
get
{
// make sure we need to check this.
//
if (_disableDesignerFeatures == DisableDesignerFeaturesUnknown)
{
_disableDesignerFeatures = DisableDesignerFeaturesNo;
IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
// the magic key is on the root components's IDictionaryService.
//
if (host != null)
{
IComponent rootComponent = host.RootComponent;
if (rootComponent != null && rootComponent.Site != null)
{
IDictionaryService dictionaryService = (IDictionaryService)rootComponent.Site.GetService(typeof(IDictionaryService));
// check for the key and set up the state if we find it.
//
if (dictionaryService != null && dictionaryService.GetValue(ExtenderControlDictionaryKey) != null)
{
_disableDesignerFeatures = DisableDesignerFeaturesYes;
}
}
}
}
return (_disableDesignerFeatures == DisableDesignerFeaturesNo);
}
}
/// <summary>
/// The ExtenderControl this designer is attached to.
/// </summary>
protected T ExtenderControl
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
get
{
return Component as T;
}
}
/// <summary>
/// The name of the ExtenderProperty that will appear in the properties of potential target controls.
///
/// By default this is the name of the Extender (e.g. "TextBoxWatermarkExtender") but can be customized by overriding this property.
/// </summary>
protected virtual string ExtenderPropertyName
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
get
{
return String.Format(CultureInfo.InvariantCulture, "{0} ({1})",TypeDescriptor.GetComponentName(Component), ExtenderControl.GetType().Name);
}
}
/// <summary>
/// Called to check if we can extend a given control. We return true if the control has the same ID a
/// our extender control target.
/// </summary>
/// <param name="targetControl"></param>
/// <returns></returns>
public bool CanExtend(object extendee)
{
Control extendeeControl = extendee as Control;
bool canExtend = false;
if (DesignerFeaturesEnabled && extendeeControl != null)
{
canExtend = (extendeeControl.ID == ExtenderControl.TargetControlID);
if (canExtend) {
if (_renameProvider == null) {
// hook up the rename prvider.
_renameProvider = new ExtenderPropertyRenameDescProv(this, extendeeControl);
TypeDescriptor.AddProvider(_renameProvider, extendeeControl);
}
}
}
return canExtend;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_renameProvider != null)
{
TypeDescriptor.RemoveProvider(_renameProvider, Component);
_renameProvider.Dispose();
_renameProvider = null;
}
}
base.Dispose(disposing);
}
[
Category("Extenders"),
Browsable(true),
TypeConverter(typeof(ExtenderPropertiesTypeDescriptor))
]
public object GetExtender(object control)
{
Control c = control as Control;
// we return a wrapper object here. This lets us avoid creating
// the actual target properties object until the '+' is clicked in
// the property browser.
//
// If we don't do this, an empty properties would get added and then (potentially) serialized out to code.
//
if (DesignerFeaturesEnabled && c != null)
{
return new ExtenderPropertiesProxy(ExtenderControl, "TargetControlID");
}
return null;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
public override void Initialize(IComponent component)
{
base.Initialize(component);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
protected override void PreFilterAttributes(System.Collections.IDictionary attributes)
{
base.PreFilterAttributes(attributes);
if (!DesignerFeaturesEnabled)
{
return;
}
TargetControlTypeAttribute targetCtrlTypeAttribute = (TargetControlTypeAttribute)TypeDescriptor.GetAttributes(this)[typeof(TargetControlTypeAttribute)];
if (targetCtrlTypeAttribute != null && !targetCtrlTypeAttribute.IsDefaultAttribute())
{
attributes[typeof(TargetControlTypeAttribute)] = targetCtrlTypeAttribute;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods", Justification = "Security handled by base class")]
protected override void PreFilterProperties(System.Collections.IDictionary properties)
{
base.PreFilterProperties(properties);
if (!DesignerFeaturesEnabled)
{
return;
}
string[] propertyNames = new string[properties.Keys.Count];
properties.Keys.CopyTo(propertyNames, 0);
foreach (string propertyName in propertyNames) {
PropertyDescriptor pd = (PropertyDescriptor)properties[propertyName];
if (propertyName == "TargetControlID") {
// get the control type.
//
TargetControlTypeAttribute targetControlType = (TargetControlTypeAttribute)TypeDescriptor.GetAttributes(ExtenderControl)[typeof(TargetControlTypeAttribute)];
if (targetControlType != null && !targetControlType.IsDefaultAttribute()) {
Type genericType = typeof(TypedControlIDConverter<>).MakeGenericType(targetControlType.TargetControlType);
properties[propertyName] = TypeDescriptor.CreateProperty(pd.ComponentType, pd, new TypeConverterAttribute(genericType));
}
}
ExtenderControlPropertyAttribute extenderPropAttr = (ExtenderControlPropertyAttribute)pd.Attributes[typeof(ExtenderControlPropertyAttribute)];
if (extenderPropAttr == null || !extenderPropAttr.IsScriptProperty) {
continue;
}
BrowsableAttribute browsableAttr = (BrowsableAttribute)pd.Attributes[typeof(BrowsableAttribute)];
if (browsableAttr.Browsable == BrowsableAttribute.Yes.Browsable) {
properties[propertyName] = TypeDescriptor.CreateProperty(pd.ComponentType, pd, BrowsableAttribute.No, ExtenderVisiblePropertyAttribute.Yes);
}
}
}
/// <summary>
/// This provider allows us to rename the extender provided property
/// </summary>
private class ExtenderPropertyRenameDescProv : FilterTypeDescriptionProvider<IComponent>
{
private ExtenderControlBaseDesigner<T> _owner;
public ExtenderPropertyRenameDescProv(ExtenderControlBaseDesigner<T> owner, IComponent target)
: base(target)
{
_owner = owner;
FilterExtendedProperties = true;
}
protected override PropertyDescriptor ProcessProperty(PropertyDescriptor baseProp)
{
if (baseProp.Name == "Extender" && baseProp.ComponentType == _owner.GetType() && _owner.ExtenderPropertyName != null)
{
// if the property is called "Extender", rename it with the name specified by the designer.
//
return TypeDescriptor.CreateProperty(baseProp.ComponentType, baseProp,
new DisplayNameAttribute(_owner.ExtenderPropertyName));
}
return base.ProcessProperty(baseProp);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -