当前位置:编程学习 > C#/ASP.NET >>

我的web控件开发经历(2)——普通类的改装

不希望有太多的未知。如果从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 成员


        
IDisposable 成员
    }


   
}

往工具箱放不报错,但看不见。是不是“一个都不能少”呢?把8个都实现了再放,还是一样看不见。反射出control的代码(反射工具reflector可到我上传的资源去下http://download.csdn.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 成员


        
IDisposable 成员

        
IControlDesignerAccessor 成员

        
IParserAccessor 成员

        
IUrlResolutionService 成员

        
IDataBindingsAccessor 成员

        
IControlBuilderAccessor 成员

        
IExpressionsAccessor 成员
    }



}

拖到页面,说什么“不具有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 成员

        
IDisposable 成员

        
IControlDesignerAccessor 成员

        
IParserAccessor 成员

        
IUrlResolutionService 成员

        
IDataBindingsAccessor 成员

        
IControlBuilderAccessor 成员

        
IExpressionsAccessor 成员
    }



}

再拖到页面,报别的错误,不管,在浏览器查看:

再到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 成员

        
IDisposable 成员

        
IControlDesignerAccessor 成员

        
IParserAccessor 成员

        
IUrlResolutionService 成员

        
IDataBindingsAccessor 成员

        
IControlBuilderAccessor 成员

        
IExpressionsAccessor 成员
    }
    
}

再浏览,不报错了。但在设计器中还是报错,经过分析我觉得是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

<
补充:asp.net教程,.Net开发 
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,