不希望有太多的未知。如果从control继承,觉得有太多的未知。
尝试1:创建一个普通类库,要public:
using System;
namespace test1
{
public class test1
{
}
}
编译成dll,准备放在测试的aspx页面上,结果连工具箱也放不上,报错。
查看control的定义,8个接口,第一个:IComponent
using System;
using System.ComponentModel;
namespace test1
...{
public class test1:IComponent
...{
IComponent 成员#region IComponent 成员
public event EventHandler Disposed;
public ISite Site
...{
get
...{
throw new Exception("The method or operation is not implemented.");
}
set
...{
throw new Exception("The method or operation is not implemented.");
}
}
#endregion
IDisposable 成员#region IDisposable 成员
public void Dispose()
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
}
}
往工具箱放不报错,但看不见。是不是“一个都不能少”呢?把8个都实现了再放,还是一样看不见。反射出control的代码(反射工具reflector可到我上传的资源去下http://download.111cn.net/user/whwqs),发现control头部的元数据,把它加上去。工具箱中可以看见了。
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web;
using System.ComponentModel.Design.Serialization;
using System.Security.Permissions;
namespace test1
...{
[DesignerCategory("Code"), ToolboxItemFilter("System.Web.UI", ToolboxItemFilterType.Require), DesignerSerializer("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, Microsoft.VisualStudio.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), DefaultProperty("ID"), Designer("System.Web.UI.Design.ControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ToolboxItem("System.Web.UI.Design.WebControlToolboxItem, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), Themeable(false), Bindable(true), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class test1 : IComponent, IDisposable, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
...{
IComponent 成员#region IComponent 成员
public event EventHandler Disposed;
public ISite Site
...{
get
...{
throw new Exception("The method or operation is not implemented.");
}
set
...{
throw new Exception("The method or operation is not implemented.");
}
}
#endregion
IDisposable 成员#region IDisposable 成员
public void Dispose()
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IControlDesignerAccessor 成员#region IControlDesignerAccessor 成员
public System.Collections.IDictionary GetDesignModeState()
...{
throw new Exception("The method or operation is not implemented.");
}
public void SetDesignModeState(System.Collections.IDictionary data)
...{
throw new Exception("The method or operation is not implemented.");
}
public void SetOwnerControl(Control owner)
...{
throw new Exception("The method or operation is not implemented.");
}
public System.Collections.IDictionary UserData
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IParserAccessor 成员#region IParserAccessor 成员
public void AddParsedSubObject(object obj)
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IUrlResolutionService 成员#region IUrlResolutionService 成员
public string ResolveClientUrl(string relativeUrl)
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IDataBindingsAccessor 成员#region IDataBindingsAccessor 成员
public DataBindingCollection DataBindings
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
public bool HasDataBindings
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IControlBuilderAccessor 成员#region IControlBuilderAccessor 成员
public ControlBuilder ControlBuilder
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IExpressionsAccessor 成员#region IExpressionsAccessor 成员
public ExpressionBindingCollection Expressions
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
public bool HasExpressions
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
}
}
拖到页面,说什么“不具有id的公共属性",再看control定义,把它的ID拷过来,改装一下,变成:
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web;
using System.ComponentModel.Design.Serialization;
using System.Security.Permissions;
namespace test1
...{
[DesignerCategory("Code"), ToolboxItemFilter("System.Web.UI", ToolboxItemFilterType.Require), DesignerSerializer("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, Microsoft.VisualStudio.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), DefaultProperty("ID"), Designer("System.Web.UI.Design.ControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ToolboxItem("System.Web.UI.Design.WebControlToolboxItem, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), Themeable(false), Bindable(true), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class test1 : IComponent, IDisposable, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
...{
string _id = "id1";
[ParenthesizePropertyName(true)]
[Filterable(false)]
[Themeable(false)]
[MergableProperty(false)]
public string ID
...{
set
...{
_id = value;
}
get
...{
return _id;
}
}
IComponent 成员#region IComponent 成员
public event EventHandler Disposed;
public ISite Site
...{
get
...{
throw new Exception("The method or operation is not implemented.");
}
set
...{
throw new Exception("The method or operation is not implemented.");
}
}
#endregion
IDisposable 成员#region IDisposable 成员
public void Dispose()
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IControlDesignerAccessor 成员#region IControlDesignerAccessor 成员
public System.Collections.IDictionary GetDesignModeState()
...{
throw new Exception("The method or operation is not implemented.");
}
public void SetDesignModeState(System.Collections.IDictionary data)
...{
throw new Exception("The method or operation is not implemented.");
}
public void SetOwnerControl(Control owner)
...{
throw new Exception("The method or operation is not implemented.");
}
public System.Collections.IDictionary UserData
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IParserAccessor 成员#region IParserAccessor 成员
public void AddParsedSubObject(object obj)
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IUrlResolutionService 成员#region IUrlResolutionService 成员
public string ResolveClientUrl(string relativeUrl)
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IDataBindingsAccessor 成员#region IDataBindingsAccessor 成员
public DataBindingCollection DataBindings
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
public bool HasDataBindings
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IControlBuilderAccessor 成员#region IControlBuilderAccessor 成员
public ControlBuilder ControlBuilder
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IExpressionsAccessor 成员#region IExpressionsAccessor 成员
public ExpressionBindingCollection Expressions
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
public bool HasExpressions
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
}
}
再拖到页面,报别的错误,不管,在浏览器查看:
再到control的反射中找到AddParsedSubObject的实现,贴过来:
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web;
using System.ComponentModel.Design.Serialization;
using System.Security.Permissions;
namespace test1
...{
[DesignerCategory("Code"), ToolboxItemFilter("System.Web.UI", ToolboxItemFilterType.Require), DesignerSerializer("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, Microsoft.VisualStudio.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), DefaultProperty("ID"), Designer("System.Web.UI.Design.ControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ToolboxItem("System.Web.UI.Design.WebControlToolboxItem, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), Themeable(false), Bindable(true), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class test1 : IComponent, IDisposable, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
...{
string _id = "id1";
[ParenthesizePropertyName(true)]
[Filterable(false)]
[Themeable(false)]
[MergableProperty(false)]
public string ID
...{
set
...{
_id = value;
}
get
...{
return _id;
}
}
IComponent 成员#region IComponent 成员
public event EventHandler Disposed;
public ISite Site
...{
get
...{
throw new Exception("The method or operation is not implemented.");
}
set
...{
throw new Exception("The method or operation is not implemented.");
}
}
#endregion
IDisposable 成员#region IDisposable 成员
public void Dispose()
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IControlDesignerAccessor 成员#region IControlDesignerAccessor 成员
public System.Collections.IDictionary GetDesignModeState()
...{
throw new Exception("The method or operation is not implemented.");
}
public void SetDesignModeState(System.Collections.IDictionary data)
...{
throw new Exception("The method or operation is not implemented.");
}
public void SetOwnerControl(Control owner)
...{
throw new Exception("The method or operation is not implemented.");
}
public System.Collections.IDictionary UserData
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IParserAccessor 成员#region IParserAccessor 成员
public void AddParsedSubObject(object obj)
...{
Control child = obj as Control;
if (child != null)
...{
//this.Controls.Add(child);
}
}
#endregion
IUrlResolutionService 成员#region IUrlResolutionService 成员
public string ResolveClientUrl(string relativeUrl)
...{
throw new Exception("The method or operation is not implemented.");
}
#endregion
IDataBindingsAccessor 成员#region IDataBindingsAccessor 成员
public DataBindingCollection DataBindings
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
public bool HasDataBindings
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IControlBuilderAccessor 成员#region IControlBuilderAccessor 成员
public ControlBuilder ControlBuilder
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
IExpressionsAccessor 成员#region IExpressionsAccessor 成员
public ExpressionBindingCollection Expressions
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
public bool HasExpressions
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
#endregion
}
}
再浏览,不报错了。但在设计器中还是报错,经过分析我觉得是IControlDesignerAccessor的成员void SetOwnerControl(Control owner)查msdn有一句话:
此成员是显式接口成员的实现。它只能在Control实例被强制转换为 IControlDesignerAccessor 接口时使用。控件设计器使用 IControlDesignerAccessor 接口对控件执行设计时操作。
看来必须是Control的实例才能在设计器正常显示,我的可是test1实例。也就是说,不从Control继承,仿照它的实现的类的实例在设计器中总不可能正常显示的。除非仿出一个设计器来。但也是有收获的:在设计器中呈现的控件是真正在内存中对应一个实例的。记住这个IControlDesignerAccessor接口吧。我们做的控件如果在设计器中呈现与种不同的设计界面时可能需要好好了解它。
接下来,有一个思路:我不理会设计器,能呈现我的控件到页面吗?答案是不可能。因为要呈现的控件必须加在控件树上。而加载方法比如:Controls.Add的参数必须是Control或它的子孙。而test1是没有办法转换为control的。
结论:在2.0或之前的框架下,要开发web控件,必须继承自Control。
推荐一篇文章:说明继承自Control继承自WebControl的不同。
http://www.cnblogs.com/mapserver/articles/392325.html