文章导航PC6首页软件下载单机游戏安卓资源苹果资源

pc软件新闻网络操作系统办公工具编程服务器软件评测

安卓新闻资讯应用教程刷机教程安卓游戏攻略tv资讯深度阅读综合安卓评测

苹果ios资讯苹果手机越狱备份教程美化教程ios软件教程mac教程

单机游戏角色扮演即时战略动作射击棋牌游戏体育竞技模拟经营其它游戏游戏工具

网游cf活动dnf活动lol周免英雄lol礼包

手游最新动态手游评测手游活动新游预告手游问答

您的位置:首页精文荟萃软件资讯 → ASP.NET 定制控件的开发(二)

ASP.NET 定制控件的开发(二)

时间:2004/10/7 18:10:00来源:本站整理作者:蓝点我要评论(0)

 复合控件的创建

创建定制控件的第三种方法是组合二个或二个以上的现有的控件。在下面的例子中,读者将以合同编程人员的身份出现,而我则是客户,我希望读者能够开发一个稍微复杂一些的控件,使我能够用来记录收到的对我的书的询价。

作为客户,我将要求读者开发一个控件,使我能够输入一本或多本书籍,每当点击一本书时,控件就会记录下对该书的点击次数,如下图所示:
 

 



这一程序的.aspx文件如下所示,除@ Page命令外,该程序的C#和VB程序是相同的:

利便控件的.aspx文件


 
 
 
 
 
     
 
 
 
 
     
 
 
 
               

 
   
 



在上面的代码中需要注意的是,BookInquiryList组件中包含许多BookCounter元素,其中有一个BookCounter元素是对应着我希望记录的书籍。这个控件非常灵活,我可以对任意数量的书进行记录。每个BookCounter元素有一个用来显示被记录书籍名字的BookName属性。

从图9中我们可以看到,每本书都由一个CountedButton定制控件进行记录,但.aspx文件中没有CountedButton控件的定义,它被完整地封装在了BookCounter定制控件中。

整个体系结构如下所示:


 


  1. BookInquiry利便控件是由WebControl派生的,实现了INamingContainer,在下面我们会提到。
     
  2. BookInquiry控件有一个由Control类派生的Controls特性。
     
  3. 在控件集合中有数量不等的BookCounter控件。
     
  4. BookCounter本身也是一个由WebControl派生得来的复合控件,WebControl也实现了INamingContainer。

    1. BookContainer的每个实例有二个特性:BookName和Count。
       
    2. Name特性是由Viewstate支持的,而且通过.aspx文件中的BookName BookName初始化。
       
    3. Count特性授权给private性质的CountedButton对象



使用BookInquiry对象的目的有二个:它是BookCounter对象的容器;它负责绘制它本身并确保它包含的BookCounter对象能够按需求绘制自己。

CountedButton控件的修改

我们需要对CountedButton控件进行一些很小的修改,下面分别是C#和VB.NET版的CountedButton控件。

修改后的CountedButton.cs文件


 


using  System;
  using  System.Web.UI;
  using  System.Web.UI.WebControls;
  using  System.ComponentModel;
 
  namespace  CustomControls
  {
        //  由System.Web.UI.WebControls.Button派生出的定制控件
        public  class  CountedButton  :  System.Web.UI.WebControls.Button
        {
 
              private  string  displayString;
 
              //  缺省的构造器
              public  CountedButton(    )
              {
                    displayString  =  "clicks";
                    InitValues(    );
              }
 
              //  重载,显示字符串
              public  CountedButton(string  displayString)
              {
                    this.displayString  =  displayString;
                    InitValues(    );
              }
 
              //  由构造器调用的函数
              private  void  InitValues(    )
              {
                    if  (ViewState["Count"]  ==  null)
                          ViewState["Count"]  =  0;
                    this.Text  =  "Click  me";
              }
 
              //  Count是ViewState中的一个特性
              public  int  Count 
            {
                  get
                  {
                        //  在构造器中初始化,不能是NULL
                          return  (int)  ViewState["Count"];
                    }
 
                    set
                    {
                          ViewState["Count"]  =  value;
                    }
              }
 
              //  覆盖OnClick事件处理程序,增大Count变量的值,并在更新按钮上的文本后调用基础类中的方法
              protected  override  void  OnClick(EventArgs  e)
              {
                    ViewState["Count"]  =    ((int)ViewState["Count"])  +  1;
                    this.Text  =  ViewState["Count"]  +  "  "  +  displayString;
                    base.OnClick(e);
              }
        }
  }



修改后的CountedButton.vb文件


 


Imports  System.ComponentModel
  Imports  System.Web.UI
  Imports  System.Web.UI.WebControls
 
  '  从System.Web.UI.WebControls.Button中派生的定制控件
  Public  Class  CountedButton
        Inherits  System.Web.UI.WebControls.Button
 
        Private  displayString  As  String
 
        '  构造器对ViewState进行初始化
        Public  Sub  New(    )
              displayString  =  "clicks"
              Init(    )
        End  Sub
 
      '  重载,显示字符串
        Public  Sub  New(ByVal  displayString  As  String)
              Me.displayString  =  displayString
              Init(    )
        End  Sub
 
        '  由构造器调用的方法
        Private  Shadows  Sub  Init(    )
              If  ViewState("Count")  =  Is  Nothing  Then
                    ViewState("Count")  =  0
                    Me.Text  =  "Click  me"
              End  If
        End  Sub
 
        '  Count是ViewState中的一个特性
        Public  Property  Count(    )  As  Integer
              Get
                    Return  CInt(ViewState("Count"))
              End  Get
              Set(ByVal  Value  As  Integer)
                    ViewState("Count")  =  Value
              End  Set
        End  Property
 
        '    覆盖OnClick事件处理程序,增大Count变量的值,并在更新按钮上的文本后调用基础类中的方法
        Protected  Overrides  Sub  OnClick(ByVal  e  As  EventArgs)
              ViewState("Count")  =  CInt(ViewState("Count"))  +  1
              Me.Text  =  CStr(ViewState("Count")  &  "  "  &  displayString
              MyBase.OnClick(e)
        End  Sub
  End  Class?)



由于我们希望按钮上显示“5 Inquiries”而不是“5 clicks”字符串,因此必须修改OnClick方法中修改按钮字符串文本的代码:


 

this.Text = ViewState["Count"] + " " + displayString;



相应的VB.NET代码是:


 

Me.Text = ViewState("Count") & " " & displayString



我们还使用了一个private性质的成员变量displayString来存储传递给构造器中的数值:


 

private string displayString;



在VB.NET中的代码为:


 

Private displayString As String



我们必须在构造器中设置这一字符串。为了保护已经使用了缺省的构造器的代码,我们必须重载构造器,新增加一个带有字符串参数的构造器:


 

public  CountedButton(string  displayString)
    {
          this.displayString  =  displayString;
          Init(    );
    }
 



在VB.NET中的代码是:


 

Public  Sub  New(ByVal  displayString  As  String)
        Me.displayString  =  displayString
        Initialize(    )
  End  Sub
 



我们可以对缺省的构造器进行修改,将displayString成员变量有值设置为一个合理的缺省值。其C#代码如下:


 

public  CountedButton(    )
  {
        displayString  =  "clicks";
        InitValues(    );
  }



相应的VB.NET代码是:


 


Public  Sub  New(    )
        displayString  =  "clicks"
        Init(    )
  End  Sub

 

 



二个构造器的代码都没有考虑private性质的辅助方法Init,它能够保证Count特性被初始化为0,并设置最初时按钮显示的字符串:


 

private  void  Init(    )
  {
        if  (ViewState["Count"]  ==  null)
              ViewState["Count"]  =  0;
        this.Text  =  "Click  me";
  }



在VB.NET中,相应的代码为:


 


Private  Shadows  Sub  Init(    )
        If  ViewState("Count")  =  Nothing  Then
              ViewState("Count")  =  0
              Me.Text  =  "Click  me"
        End  If
  End  Sub



作了上述的修改后,我们就可以在第一个复合控件━━BookCounter中使用CountedButton了。

BookCounter复合控件的创建

BookCounter复合控件用于记录和显示对某一本书查询的次数,下面分别是C#和VB.NET版的BookCounter复合控件的源代码:

C#版本的BookCounter控件源文件:BookCounter.cs


 


using  System;
  using  System.Web.UI;
  using  System.Web.UI.WebControls;
  using  System.ComponentModel;
 
  namespace  CustomControls
  {
        public  class  BookCounter  : 
            System.Web.UI.WebControls.WebControl, 
            INamingContainer
      {

            //  初始化按钮成员
              CountedButton  btn  =  new  CountedButton("inquiries");
 
              public  string  BookName 
            {
                  get
                  {
                        return  (string)  ViewState["BookName"];
                    }
 
                    set
                    {
                          ViewState["BookName"]  =  value;
                    }
              }
 
              public  int  Count
              {
                    get
                    {
                          return  btn.Count;
                    }
                    set
                    {
                          btn.Count  =  value;
                    }
              }
 
              public  void  Reset(    )
              {
                    btn.Count  =  0;
              }
 
              protected  override  void  CreateChildControls(    )
              {
                    Controls.Add(btn);
              }
        }
  }



VB.NET版的BookCounter控件的源代码: BookCounter.vb


 


Imports  System
  Imports  System.Web.UI
  Imports  System.Web.UI.WebControls
  Imports  System.ComponentModel
 
  Public  Class  BookCounter
        Inherits  System.Web.UI.WebControls.WebControl
        Implements  INamingContainer
 
        '  初始化按钮成员
        Public  btn  As  CountedButton  =  New  CountedButton("inquiries")
 
        Public  Property  BookName(    )  As  String
              Get
                    Return  CStr(ViewState("BookName"))
              End  Get
              Set(ByVal  Value  As  String)
                    ViewState("BookName")  =  Value
              End  Set
        End  Property
 
        Public  Property  Count(    )  As  Integer
              Get
                    Return  btn.Count
              End  Get
              Set(ByVal  Value  As  Integer)
                    btn.Count  =  Value
              End  Set
        End  Property
 
        Public  Sub  Reset(    )
              btn.Count  =  0
        End  Sub
 
        Protected  Overrides  Sub  CreateChildControls(    )
              Controls.Add(btn)
        End  Sub
 
  End  Class
 



INamingContainer

BookCounter类中首先需要注意的是它实现了INamingContainer界面,这是一个没有方法的“记分器”界面。这一界面的目的是识别创建新的ID名字空间的容器控件,保证所有的子控件都有对于应用程序是唯一的ID。

包含CountedButton

BookCounter类包含有CountedButton的一个实例:


 

CountedButton btn = new CountedButton("inquiries");



或:


 

Public btn As CountedButton = New CountedButton("inquiries")



btn成员是在由System.Control继承的CreateChildControls方法中被初始化的:


 

protected  override  void  CreateChildControls(    )
  {
        Controls.Add(btn);
  }
 



在VB.NET中,相应的代码为:


 


Protected  Overrides  Sub  CreateChildControls(    )
        Controls.Add(btn)
  End  Sub



CreateChildControls是在绘制的准备工作时被调用的,它使BookCounter类能够添加btn对象作为被包含的控件。

BookCounter无需覆盖Render方法,它唯一需要绘制的是CountedButton。Render缺省的操作是绘制所有的子控件,因此无需对它作任何修改就能完成其功能。

BookCounter还有二个特性:BookName和Count。BookName是在控件中显示的一个字符串,而且通过ViewState进行管理,其C#代码如下所示:


 


public  string  BookName 
{
        get
        {
                return  (string)  ViewState["BookName"];
          }
 
          set
          {
                  ViewState["BookName"]  =  value;
          }
  }



相应的VB.NET源代码为:


 


Public  Property  BookName(    )  As  String
        Get
              Return  CStr(ViewState("BookName"))
        End  Get
        Set(ByVal  Value  As  String)
              ViewState("BookName")  =  Value
        End  Set
  End  Property



Count是对一本特定的书查询的数量,记录这一数量的任务由CountedButton完成。其C#代码如下所示:


 

public  int  Count
  {
        get
        {
              return  btn.Count;
        }
        set
        {
              btn.Count  =  value;
        }
  }



相应的VB.NET源代码为:


 


Public  Property  Count(    )  As  Integer
        Get
              Return  btn.Count
        End  Get
        Set(ByVal  Value  As  Integer)
              btn.Count  =  Value
        End  Set
  End  Property



无需将该值放在ViewState中,因为按钮本身就可以对其数据进行管理。

BookInquiryList复合控件的创建

每个BookCounter对象都被包含在BookInquiryList控件集合中,该控件没有特性,只有一个Render方法,其C#和VB.NET代码如下所示:

BookInquiryList的C#代码:


 


[ControlBuilderAttribute(typeof(BookCounterBuilder)),ParseChildren(false)]
public  class  BookInquiryList  :  System.Web.UI.WebControls.WebControl,  INamingContainer
  {
 
        protected  override  void  Render(HtmlTextWriter  output)
        {
              int  totalInquiries  =  0;
              BookCounter  current;
 
              //  输出头部
              output.Write("                    "cellspacing='1'  align  =  'center'  >");
              output.Write("

");
        }
  }

BookInquiryList的VB.NET源代码:


 

Imports  System.ComponentModel
  Imports  System.Web.UI
 
    _
  Public  Class  BookInquiryList
        Inherits  System.Web.UI.WebControls.WebControl
        Implements  INamingContainer
 
        Protected  Overrides  Sub  Render(ByVal  output  As  HtmlTextWriter)
 
              Dim  totalInquiries  As  Integer  =  0
 
              '  输出头部
              output.Write("                    "cellspacing='1'  align  =  'center'  >")
              output.Write("

")
        End  Sub
 
  End  Class
 
  Friend  Class  BookCounterBuilder
        Inherits  ControlBuilder
 
        Public  Overrides  Function  GetChildControlType(  _
                    ByVal  tagName  As  String,  ByVal  attributes  As  IDictionary)  As  Type
              If  tagName  =  "BookCounter"  Then
                    Dim  x  As  BookCounter
                    Return  x.GetType
              Else
                    Return  Nothing
              End  If
        End  Function
 
        Public  Overrides  Sub  AppendLiteralString(ByVal  s  As  String)
        End  Sub
 
  End  Class

ControlBuilder和ParseChildren属性

BookCounter类必须与BookInquiryClass联合使用,ASP.NET才能将.aspx网页中的元素转换为适当的代码。完成这一工作需要用到ControlBuilder属性:

[ControlBuilderAttribute(typeof(BookCounterBuilder)),ParseChildren(false)]

ControlBuilderAttribute的参数是一个通过传递BookCounterBuilder类获取的Type对象。下面是使用C#和VB.NET编写的BookCounterBuilder源代码:

C#语言版的BookCounterBuilder


 

internal  class  BookCounterBuilder  :  ControlBuilder
  {
        public  override  Type  GetChildControlType(
              string  tagName,  IDictionary  attributes)
        {
              if  (tagName  ==  "BookCounter")
                    return  typeof(BookCounter);
              else
                    return  null;
        }
 
        public  override  void  AppendLiteralString(string  s)
        {
        }
  }
 
  VB.NET版的BookCounterBuilder 

Friend  Class  BookCounterBuilder
          Inherits  ControlBuilder
 
          Public  Overrides  Function  GetChildControlType(_
                  ByVal  tagName  As  String,  ByVal  attributes  As  Idictionary)  As  Type
              If  tagName  =  "BookCounter"  Then
                  Dim  x  As  BookCounter
                  Return  x.GetType
              Else
                  Return  Nothing
              End  If
          End  Function
 
          Public  Overrides  Sub  AppendLiteralString(ByVal  s  As  String)
          End  Sub
 
  End  Class



ASP.NET将使用由ControlBuilder中派生出的BookCounterBuilder来判断由BookCounter标记批指示的对象的类型。通过这种结合,每个BookCounter对象才能被实例化,并添加到BookInquiryClass的控件集合中。

第二个参数ParseChildren必须被设置成false,让ASP.NET知道我们已经对子属性进行了处理,无需再对它进行进一步地解析了。false值表明子属性不是外部对象的特性,而仅仅是子控件的特性。

Render

BookInquiryClass中的唯一方法是覆盖Render的方法,Render的作用是使用由每个BookCounter子控件管理的数据绘制图9中的表格。

BookInquiryClass提供了一个总的查询数字,如下图所示:


 



Figure 14-16. Total inquiries displayed

通过将totalInquiries整型变量初始化为0,然后依次遍历每个控件,将其Count特性与totalInquiries相加,就可以得到查询的总数了。除了C#中语句结束时的分号为,实现这一功能的C#和VB.NET语句相同:

totalInquiries += current.Count;

表现输出内容

通过遍历每个控件,下面的代码能够绘制出每个子控件:


 

for  (int  i  =  0;  i  <  Controls.Count;  i++)
  {
        current  =  (BookCounter)  Controls[i];
        totalInquiries  +=  current.Count;
        output.Write("



相应的VB.NET代码为:


 

For  Each  current  in  Controls
        totalInquiries  +=  current.Count
        output.Write("



局部的BookCounter对象型current变量的值被赋为控件集合中的每个对象:


 

for  (int  i  =  0;  i  <  Controls.Count;  i++)
  {
        current  =  (BookCounter)  Controls[i];
 



然后就可以利用下面的代码计算totalInquiries:


 

totalInquiries += current.Count;



然后我们就可以继续绘制对象了。通过利用current的BookName特性,HtmlTextWriter可以用来创建一个行并显示书的名字:


 

output.Write("
" + current.BookName + "



接下来,我们绘制一个TD标记,在该标记内我们让BookCounter对象绘制自己。最后,使用RenderEndTag来绘制一个结束性的TD标记,并使用HTMLTextWriter的Write方法绘制行结束标记。


 

output.RenderBeginTag("TD");
  current.RenderControl(output);
  output.RenderEndTag(    ); 
  output.Write("



下面的代码使被包含的控件自己绘制自己:


 

current.RenderControl(output);



上面的代码会调用BookCounter的Render方法。由于我们没有覆盖该方法,调用的仍然是基础类中的Render 类。唯一被包含的对象是CountedButton,由于我们没有覆盖CountedButton中的Render方法,在绘制该按钮时调用的仍然是基础类Button中的Render方法。

查询总数的绘制

所有的子控件绘制完毕后,BookInquiryList将创建一个新的行,显示总的查询次数:


 

output.Write("



至此,作为合同编程人员的你,就完成了任务。

结束语

在上面的文章中,我们讨论了开发定制控件的三种途径,尤其是通过一个例子,详细论述了建立复合控件的过程。在具体的工作中,灵活地运用这三种方式创建定制控件,使我们的开发工作事半功倍。

 

相关阅读 Mac访问Windows共享文件夹Windows 7正版系统验证方法windows 8.1系统版本号查看方法Windows 8.1系统电话激活时无法输入微软返回代码解决方法Windows 8如何调整屏幕分辨率windows8.1磁盘占用100%解决方法Mac双系统如何删除Boot Camp安装的Windows分区Apple教你如何在Mac 上运行 Windows

文章评论
发表评论

热门文章 360随身Wifi 4G版什么怎样提高origin下载速百度收购PPS已敲定!3

最新文章 伊森卡特的消失通关流千牛怎么设置自动回复 增加新功能,S版Moto G喜获Android 4.4.4更鸡肋?谷歌Play Music发布更新版本千牛怎么设置自动回复​千牛云盘怎么用

人气排行 xp系统停止服务怎么办?xp系统升级win7系统方office2013安装教程图解:手把手教你安装与同步推是什么?同步推使用方法介绍QQ2012什么时候出 最新版下载VeryCD镜像网站逐个数,电驴资料库全集利用PHP程序设定防止MySQL注入或HTML表单滥web服务器和应用服务器的区别安卓android 系统支持什么视频格式