ASP.NET控件开发之控件生成器浅析

开发 后端
ASP.NET控件开发之控件生成器主要是指什么呢?ASP.NET控件开发之控件生成器主要有那些需要注意的呢?那么本文就向你介绍这方面的内容。

上一篇讨论了为服务器控件添加客户端功能,这一篇我们所要讲的是控件生成器

ASP.NET控件开发之控件生成器1.错误的代码,无法解析

首先来看一段简单的代码

正确  
           ﹤asp:Wizard ID="Wizard1" runat="server"﹥  
               ﹤WizardSteps﹥  
                   ﹤asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1"﹥  
                       21212﹤/asp:WizardStep﹥  
                   ﹤asp:WizardStep ID="WizardStep2" runat="server" Title="Step 2"﹥  
                   ﹤/asp:WizardStep﹥  
               ﹤/WizardSteps﹥  
           ﹤/asp:Wizard﹥  
           错误  
           ﹤asp:Wizard ID="Wizard2" runat="server"﹥  
               ﹤asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1"﹥  
                   21212﹤/asp:WizardStep﹥  
               ﹤asp:WizardStep ID="WizardStep2" runat="server" Title="Step 2"﹥  
               ﹤/asp:WizardStep﹥  
           ﹤/asp:Wizard﹥  
           ﹤br /﹥  
           ﹤br /﹥  
           ﹤asp:Label ID="Label1" runat="server" Text="Label"﹥  
               ﹤asp:TextBox ID="TextBox2" runat="server"﹥﹤/asp:TextBox﹥  
           ﹤/asp:Label﹥  
           ﹤br /﹥  
           ﹤asp:TextBox ID="TextBox3" runat="server"﹥12345﹤/asp:TextBox﹥  
           ﹤br /﹥  
           ﹤asp:Label ID="Label2" runat="server" Text="Label"﹥12345﹤/asp:Label﹥  
           ﹤br /﹥  
           ﹤br /﹥  
           ﹤asp:TextBox ID="TextBox1" runat="server"﹥  
       ﹤asp:Label runat="server" Text="Label"﹥﹤/asp:Label﹥  
           ﹤/asp:TextBox﹥ 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

Wizard为asp.net2.0新增的一个控件,这个页面发生两个错误,如下图

页面发生两个错误  

运行此页面后则会报错,出现以下提示

ASP.NET控件开发之控件生成器之分析器错误

这里有一个问题,.net提供我们控件时,我们已经形成一种定向思维,控件就是那样写的,如DropDownList,其中只能是套﹤asp:ListItem﹥的,那我为什么就不能套别的属性呢?Wizard控件为什么就要加一个WizardSteps属性才可以正常运行呢?当我们思考到这里,我们就该寻找答案.

ASP.NET控件开发之控件生成器2.从ParseChildren元数据属性讲起

从第五篇开始,我们多次用到了ParseChildren此特性.还请大家先看MSDN对其的解释,其有三种情况

(1)ParseChildren(true)     第5篇我们使用集合属性的时候我们曾经这样定义,如下代码

[ParseChildren(true)]  
 public class Custom: Control  
 {  
 } 
  • 1.
  • 2.
  • 3.
  • 4.

(2)ParseChildren(true,"﹤Default Property﹥") 第10篇当我们定义集合属性时,我们曾这样定义

DropItemList为集合属性

[ParseChildren(true"DropItemList")]  
public class DropColor:WebControl  
 {  

  • 1.
  • 2.
  • 3.
  • 4.

(3)ParseChildren(false)  这个我们没用过,也是我们要讲的内容,当其内部定义为flase时,那么放在此控件内的元素将被解析成控件,应该说是页分析器ControlBuilder 类.这里大家可以看看MSDN文档对ControlBuilder 类的解释,至少要先知道这一点

默认情况下,页上的每个控件都与一个默认的 ControlBuilder 类关联。

下面我们慢慢看下来.

ASP.NET控件开发之控件生成器3.控件与集合属性

让我们再次回忆一下ParseChildren的用法,本次的示例代码取自asp.net2.0揭密

(1)ParseChildren(true,"﹤Default Property﹥")的使用

此控件实现效果为随机显示一个内部控件内容

RItem为一个继承Control的控件,其内部未实现任何东西,你可以在其控件内部输出呈现,记得上面说的ControlBuilder 类默认关联

ASP.NET控件开发之控件生成器示例一

[ParseChildren(true"Items")]  
public class ItemRotator : CompositeControl  
{  
    private ArrayList _items = new ArrayList();  
 
    [Browsable(false)]  
    public ArrayList Items  
    {  
        get { return _items; }  
    }  
 
    protected override void CreateChildControls()  
    {  
        Random rnd = new Random();  
        int index = rnd.Next(_items.Count);  
        Control item = (Control)_items[index];  
        this.Controls.Add(item);  
    }  
}  
 
public class RItem : Control  
{  
 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

ASP.NET控件开发之控件生成器页面代码

﹤custom:ItemRotator  
    id="ItemRotator1" 
    Runat="server"﹥  
    ﹤custom:ritem ID="Item1" runat="server"﹥  
        First Item  
    ﹤/custom:ritem﹥  
    ﹤custom:ritem ID="Item2" runat="server"﹥  
        Second Item  
        ﹤asp:Calendar  
            id="Calendar1" 
            Runat="server" /﹥  
    ﹤/custom:ritem﹥  
    ﹤custom:ritem ID="Item3" runat="server"﹥  
        Third Item  
    ﹤/custom:ritem﹥  
﹤/custom:ItemRotator﹥ 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.


效果就不说了,随机显示ritem控件的内容,注意以上控件定义了一个Items集合属性

另外改进的话就是我们第十篇的讲的,为Ritem定义属性,作为一个集合属性,这里就不再列出代码.

(1)ParseChildren(false)的使用

此控件未添加属性,而多了一个方法AddParsedSubObject()

控件有默认的页面分析逻辑,重写AddParsedSubObject方法,可以向控件添加子控件

ASP.NET控件开发之控件生成器示例二

[ParseChildren(false)]  
 public class ContentRotator : WebControl  
 {  
 
     protected override void AddParsedSubObject(object obj)  
     {  
         if (obj is Content)  
             base.AddParsedSubObject(obj);  
     }  
 
     protected override void RenderContents(HtmlTextWriter writer)  
     {  
         Random rnd = new Random();  
         int index = rnd.Next(this.Controls.Count);  
         this.Controls[index].RenderControl(writer);  
     }  
 }  
 [  
 ToolboxItem(false)  
 ]  
 public class Content : Control  
 {  
 } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

ASP.NET控件开发之控件生成器页面代码

﹤custom:ContentRotator  
        id="ContentRotator1" 
        Runat="server"﹥  
        ﹤custom:Content  
            id="Content1" 
            Runat="server"﹥  
            显示的***项,此不为属性      
        ﹤/custom:Content﹥      
        ﹤custom:Content  
            id="Content2" 
            Runat="server"﹥  
            显示的第二项,此不为属性  
            ﹤asp:Calendar  
                id="Calendar1" 
                Runat="server" /﹥      
        ﹤/custom:Content﹥      
        ﹤custom:Content  
            id="Content3" 
            Runat="server"﹥  
            显示的第三项,此不为属性    
        ﹤/custom:Content﹥    
    ﹤/custom:ContentRotator﹥ 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

注意:ContentRotator无任何属性(其内部添加的为控件),而是用AddParsedSubObject 方法向控件添加了子控件,而不像ItemRotator控件一样,其内部是属性而非控件.

ASP.NET控件开发之控件生成器4.修改默认解析逻辑

上面已经说过每个控件都有默认的解析逻辑,其通过ControlBuilder 类来实现,可以通过重写其方法来自定义解析逻辑.下面通过一个例子来说明,它把一个控件以自定义标签所代替

以下列出部分代码

ASP.NET控件开发之控件生成器示例三

//自定义页分析器  
public class ServerTabsBuilder : ControlBuilder  
{  
    public override Type GetChildControlType(string tagName, IDictionary attribs)  
    {  
        if (String.Compare(tagName, "tab"true) == 0)  
            return typeof(ServerTab);  
        else 
            return null;  
    }  
}  
 
[ToolboxItem(false)]  
public class ServerTab : Control  
{  
    private string _Text;  
 
    public string Text  
    {  
        get { return _Text; }  
        set { _Text = value; }  
    }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

(1)ServerTabsBuilder类重写了ControlBuilder类的

GetChildControlType 方法  获取与子标记对应的控件类型的 Type

在此方法中,其以tab标签代替了ServerTab控件,改写了页分析逻辑

ControlBuilder类常用的还有AllowWhitespaceLiterals 方法 其指定控件之间是否允许存在空白,大家可以重写此方法,然后测试下就明白了

(2)定义一个简单的ServerTab控件.

还须在父控件中重写AddParsedSubObject方法将ServerTab控件添加到子控件中

protected override void AddParsedSubObject(object obj)  
{  
    if (obj is ServerTab)  
        base.AddParsedSubObject(obj);  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

(3)***还需要把控件生成器跟控件关联起来,当然还要设置ParseChildren(false)

[ControlBuilder(typeof(ServerTabsBuilder))]  
[ParseChildren(false)]  
public class ServerTabs : WebControl, IPostBackEventHandler  
{  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

好了,这里主要代码就实现了,呈现代码大家可在后面下载,下面看下页面代码

﹤%--以上省略css代码--%﹥  
    ﹤custom:ServerTabs  
        ID="ServerTabs1" 
        Runat="Server"﹥  
        ﹤tab Text="First Tab"﹥  
        ﹤asp:Label ID="Label1" runat="server" Text="Label"﹥﹤/asp:Label﹥  
          Contents of the first tab  
        ﹤/tab﹥      
        ﹤tab Text="Second Tab"﹥  
          Contents of the second tab  
        ﹤/tab﹥      
        ﹤tab Text="Third Tab"﹥  
          Contents of the third tab  
        ﹤/tab﹥      
    ﹤/custom:ServerTabs﹥ 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

以上镶套代码为tab标签,而非﹤custom:ServerTabs﹥﹤/custom:ServerTabs﹥,但实现效果是一样的,只是我们改了默认的页分析逻辑,自定义了控件页生成器(分析器)看下效果(当重新编译后需要重新启动vs2005才能看到效果)

自定义了控件页生成器 

好了,这次的主题也讲完了,这里需要注意的是asp.net2.0中复合控件只需要继承CompositeControl类即可.

ASP.NET控件开发之控件生成器方面的内容那个就向你介绍到这里,希望对你了解ASP.NET控件开发之控件生成器有所帮助。

【编辑推荐】

  1. ASP.NET控件开发基础之类型转换器浅析
  2. ASP.NET控件开发基础之实现控件集合属性
  3. ASP.NET控件开发基础之自定义视图状态管理
  4. ASP.NET控件开发基础之为子控件添加样式
  5. ASP.NET控件开发基础之服务器控件客户端功能
责任编辑:仲衡 来源: 博客园
相关推荐

2009-08-07 15:24:16

ASP.NET模板控件

2009-08-06 15:21:45

ASP.NET控件开发RenderConte

2009-08-06 09:18:01

ASP.NET自定义控ASP.NET控件开发

2009-07-28 16:21:03

Asp.net AjaAutoComplet

2009-08-06 18:18:27

ASP.NET控件开发ASP.NET复合控件

2009-08-05 18:46:21

ComboBox显示ASP.NET控件开发

2009-08-07 15:34:15

ASP.NET数据绑定

2009-07-27 17:25:53

ASP.NET验证控件

2009-08-05 17:11:51

ASP.NET控件开发ASP.NET服务器控

2009-08-07 17:41:07

ASP.NET Web

2009-08-06 17:52:45

ASP.NET控件开发自定义控件

2009-08-05 18:32:28

HtmlTextWriASP.NET控件开发

2009-07-28 09:32:41

ASP.NET自定义控

2009-08-07 17:49:44

控件设计器

2009-08-06 18:32:00

ASP.NET控件开发ASP.NET复合控件

2009-08-04 10:43:59

ASP.NET控件开发

2009-08-06 13:08:23

ASP.NET控件开发

2009-08-07 17:59:35

控件设计器

2009-07-24 09:57:25

ASP.NET HTM

2009-08-07 16:32:52

ASP.NET控件设计时支
点赞
收藏

51CTO技术栈公众号