天天看点

开发ASP.NET定制控件

定制控件的价值:1.代码重用   2.快速页面开发   3.通过控件,使修改页面更加容易

什么是ASP.NET控件?

服务器端Web UI组件:它有属性、方法和事件;呈现成标注(HTML,XML,script,etc);处理posted数据和用户行为;封装逻辑;多种呈现选项。一个控件是一个.NET类型,基类是System.Web.UI.Control,System.Web.UI.WebControls.WebControl

页面/控件处理

第一次载入:Init(实例化每个控件,设置为初始状态,加入控件树)--》Load(运行用户代码,测试IsPostBack条件来数据绑定到第一批值)--》PreRender(CreateChildControls()确保控件准备好被呈现)--》控件存储状态值(如果与初始值不同)--》Render(每个控件将自身呈现到响应中)--》Dispose(释放页面和所有控件)

Postback:比上述多了三个步骤,在Init和Load中加了个LoadViewState(从ViewState载入控件的上一次状态);在Load和PreRender之间加入了Postback data(posted数据(HTTP表单中)传递到响应控件)和postback(按照在树中的次序触发控件事件,除了导致Post的控件,它最后触发)

两种创建控件的方法:

用户控件(页面作为控件):容易创建,存作为(.ascx) 的页面,支持部分页面缓存,用于单个应用,缺少设计时支持。运行时动态编译,无法添加到工具箱,共享它的唯一方法是将之复制到另一个应用程序中。

定制控件:技术要求高一些,支持多个应用(GAC),设计时支持非常强大。它是所有开发人员都可以使用的可视化设计工具。

为设计时呈现(Render)实施一个控件设计器:

System.Design.dll提供了设计时呈现的基类。

Override GetDesignTimeHtml()默认的设计时输出内容

设计时和运行时的HTML输出是不同的处理方式

Designer类在控件的属性列表中被指定

使用呈现(Render)方法:

从Control类继承时,使用Render()方法;

从WebControl类继承时,覆盖RenderContents方法;

控件的默认基本标签是<span>标签;

当创建一个继承类的实例时,需要指定哪个基类的构造函数需要被调用,例如base(HtmlTextWriterTag.A)就是创建<a>标记

使用AddAtributesToRender()方法为控件添加HTML属性和风格。

触发服务器端事件

将服务器端客户事件映射到服务器事件

客户端的事件通过HTTP表单发一个POST至服务器端,服务器端的注册控件以接收postback事件通知。控件注册是通过委派delegate的数据类型事件会触发相应的方法去注册。如果希望自己开发的控件能够触发相应的事件,定义的类必须从IPostBackEventHandler继承过来,它是一个接口继承,它会触发一个postback事件,这个事件调用了事件处理函数,比如:Button1_Click()

用到的接口为IPostBackEventHandler(定义了ASP.NET服务器控件必须实现的方法来处理),相应的函数是RaisePostBackEvent(),触发OnClick(),调用事件处理函数Button1_Click()

使用HtmlTextWriter方法

HtmlTextWriter具备在不同的HTML版本之间,自动转换的功能,可以适应不同的浏览器。

多次调用HtmlTextWriter.Write,比构造一个复杂的字符串,然后作为参数调用一次,效率要更高。

HtmlTextWriter方法使得代码可读性和可用性更高

开发组合控件

INamingContainer接口确定容器控件在页面的对象结构下,创建一个新的名称控件ID,也就是它为某个.ASPX文件中的所有控件提供一个唯一的名称控件。

EnsureChildControls()确定服务器控件是否包含子控件,如果不包含,它将创建子控件。

CreateChildControls()通知服务器控件创建它所包含的所有子控件。

定制控件的使用范例

通过一些预定义的类,定制控件可以被快速开发出来,例如Table,HyperLink以及Label

可以用Postback事件处理来传递客户端可视化数据到后端数据库

创建配置文件(例如topLinks.xml)为web应用程序提供了一种快速并且高效的解决方案

总结:

WebControl类从Control类继承过来,增加了一些web用户控件的通用属性

把控件项目和web应用程序项目添加到同一个解决方案中,可以更加容易调试,构建,以及测试和开发。

控件可以添加到工具箱,或者全局程序集缓冲区(GAC),以便更多的开发人员都可以使用。

组合控件被编译为一个固定的程序集(.dll)

HtmlTextWriter提供了很多实用的方法来简化HTML标记的构造。

在客户端Post到服务器时,RaisePostBackEvent被触发,从而服务器控件可以进行相应的处理。

实例1:创建一个简单的定制控件

1.新建“web控件库项目”,可以看到控件继承自WebControl,

2.编译此项目,可在bin目录中看到已生成的.dll组件

3.在同一个解决方案中加入一个asp.net web应用程序

4.在工具箱的常规选项中右击选择“添加/移除项”,将刚才生成的组件选入

5.在WebForm1.aspx的设计界面中将刚在工具箱上生成的组件拖放至界面中。

6.在控件的文本属性中输入“Hello,Control!"

7.在自定义控件中添加一个Speed属性,用于控制滚动速度

8.在Render事件中增加 output.Write("<marquee scrollDelay=/""+Speed.ToString()+"/">"+Text+"</marquee>");

9.在控件属性栏中可见Speed属性,设值为1000,可见滚动速度变慢

实例2:修改工具箱中组件的图标

1.在组件项目中添加一个位图文件,名称与控件名称相同

2.设计位图文件

3.在位图的属性中有一个“生成操作”属性,修改其值为“嵌入的资源”

4.编译,将web应用程序项目工具箱中的组件移除,重新添加,可看到更改的图标

实例3:为设计时呈现(Render)实施一个控件设计器,添加一个设计类

1.在控件项目中添加一个Designer.cs的类文件,添加System.IO; System.Web.UI;System.Web.UI.WebControls的引用

2.在组件项目中添加引用System.Desinger.dll

3.为Designer类添加基类public class Designer:System.Web.UI.Design.ControlDesigner

4.重新Designer基类的方法public override string GetDesignTimeHtml(),小技巧:在输入public override后直接输入Get……会自动出现下拉列表,直接选择GetDesignTimeHtml会自动添加整个函数

5.修改GetDesignTimeHtml方法,添加字符串StringWriter sw=new StringWriter();添加HtmlTextWriter tw=new HtmlTextWriter();返回字符串return sw.ToString();

6.重新编译代码生成组件

7.修改自定义控件属性,Designer("WebControlLibrary1.Designer,WebControlLibrary1"),DefaultProperty("Text")

8.重新编译,可以看到web应用程序中设计的呈现已经被修改,但执行的结果不变

9.继续在GetDegnTimeHtml方法中添加方法

   HyperLink hl=new HyperLink();

   hl.Text="Hello,Control";

   hl.NavigateUrl="http://www.microsoft.com";

   hl.RenderControl(tw);

   tw.Write(HtmlTextWriter.SpaceChar);

   Label lbl=new Label();

   lbl.Text=hl.NavigateUrl;

   lbl.BackColor=System.Drawing.Color.AliceBlue;

完成后可在设计界面中看到上述的改动

实例4:继承自Control和WebControl类的区别,Control类定义了最基本的属性,WebControl继承自Control,额外定义了许多属性,可以在自定义类修改继承的类后在web应用程序中调用的该控件属性栏中看到区别。

实例5:如何使用Render方法

1)    Render方法在控件类中,它不显示属性,如

"Hello,Control"<marquee scrollDelay="10">"Hello,Control"</marquee>

为了增加属性,将Render改为RenderContents,它会将可视化的属性都添加进来,放在<span>标记中

如:<span id="WebCustomControl11" style="height:8px;width:32px;Z-INDEX: 101; LEFT: 136px; POSITION: absolute; TOP: 136px">"Hello,Control"<marquee scrollDelay="100">"Hello,Control"</marquee></span>

2)   将RenderContents的语句改为

 HyperLink hl=new HyperLink();

   hl.NavigateUrl="http://www.microsoft.com";

   hl.RenderControl(output);

编译控件执行web应用程序生成的代码为:

<span id="WebCustomControl11" style="height:8px;width:32px;Z-INDEX: 101; LEFT: 136px; POSITION: absolute; TOP: 136px"><a href="http://www.microsoft.com">hello,control!</a></span>

3) span标记可以修改,只需要定义类的构造函数

举例:创建类的构造函数,并让它继承基类public WebCustomControl1():base(HtmlTextWriterTag.A);添加AddAttributesToRender函数:

writer.AddAttribute(HtmlTextWriterAttribute.Onclick,"alert('You choose a page out of this site');");

   writer.AddAttribute(HtmlTextWriterAttribute.Href,"http://www.tom.com");

   base.AddAttributesToRender (writer);

为基类标记添加属性并显示

修改RenderContents函数,只需显示文本:output.Write(Text)(注意:文本的其他属性已经被构造函数所添加)

编译控件执行web应用程序生成的代码为:

<a οnclick="alert('You choose a page out of this site');" href="http://www.tom.com" id="WebCustomControl11" style="height:8px;width:32px;Z-INDEX: 101; LEFT: 136px; POSITION: absolute; TOP: 136px">"Hello,Control"</a>

实例6:处理postback事件

为已生成的控件类添加继承IPostBackEventHandler,再按Tab键会自动生成RaisePostBackEvent的方法,这个方法是这个被继承接口必须实现的方法,也就是必须触发一个事件

在定义这个方法之前,先定义一个事件,它相当于一个委托的数据类型。public event EventHandler Click;

再定义一个触发的事件方法

protected virtual void OnClick(EventArgs e)

  {

   if (Click!=null)

   {

    Click(this,e);

   }

   Page.Response.Redirect("http://www.microsoft.com");

  }

接着实现RaisePostBackEvent方法,调用OnClick(EventArgs.Empty);

还需要修改AddAttributesToRender函数,将writer.AddAttribute(HtmlTextWriterAttribute.Href,"http://www.tom.com");语句改为writer.AddAttribute(HtmlTextWriterAttribute.Href,"javascript:"+Page.GetPostBackEventReference(this));说明:Page.GetPostBackEventReference是客户端脚本的引用,它会执行客户端脚本,触发相应的事件执行。

编译执行web应用程序生成的代码为

<a οnclick="alert('You choose a page out of this site');" href="javascript:__doPostBack('WebCustomControl11','')" target="_blank" rel="external nofollow" id="WebCustomControl11" style="height:8px;width:32px;Z-INDEX: 101; LEFT: 136px; POSITION: absolute; TOP: 136px">"Hello,Control"</a>

以上都是在控件中实现的功能,如果使使用控件的开发者也能捕捉控件事件

在使用控件的web页面中添加方法

  private void WebCustomControl1_Click(object sender,System.EventArgs e)

  {

   TextBox1.Text="Clicked!";  说明:TextBox1为文本输入框ID

理WebCustomControl11.Click+=new EventHandler(this.WebCustomControl1_Click);

实例7:使用HtmlTextWriter方法

在RenderContents中添加语句:

output.AddAttribute(HtmlTextWriterAttribute.Size,"18"); 

   output.RenderBeginTag(HtmlTextWriterTag.Font);

   output.Write(Text);

   output.RenderEndTag();

修改AddAttributesToRender函数,将writer.AddAttribute(HtmlTextWriterAttribute.Href,"javascript:"+Page.GetPostBackEventReference(this));语句改为writer.AddAttribute(HtmlTextWriterAttribute.Onclick,"javascript:"+Page.GetPostBackEventReference(this));

编译执行查看文本显示

也可以在属性中添加风格,如在AddAttributersToRender方法中添加如下代码

  protected override void AddAttributesToRender(HtmlTextWriter writer)

  {

   //writer.AddAttribute(HtmlTextWriterAttribute.Onclick,"alert('You choose a page out of this site');");

   //writer.AddAttribute(HtmlTextWriterAttribute.Href,"http://www.tom.com");

   writer.AddAttribute(HtmlTextWriterAttribute.Onclick,"javascript:"+Page.GetPostBackEventReference(this));

   writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,"darkgreen"); //设置属性背景色为暗绿

   writer.AddStyleAttribute(HtmlTextWriterStyle.TextDecoration,"underline"); //设置下划线

   writer.AddAttribute("onmouseover","this.style.cursor='hand'"); //设置鼠标滑过时为手形

   base.AddAttributesToRender (writer);

  }

实例8:开发组合控件

1.首先创建一个asp.net应用程序,并在解决方案中添加控件库项目

2.编写控件代码

public class ctrl:Control,INamingContainer

 {

  public int Value

  {

   get

   {

    this.EnsureChildControls();//确保所有子控件已创建,如果没有创建,调用CreateChildControls( )方法

    return Int32.Parse(((TextBox)Controls[1]).Text);

   }

   set

   {

    this.EnsureChildControls();

    ((TextBox)Controls[1]).Text=value.ToString();

   }

  }

  protected override void CreateChildControls()  //重写CreateChildControls方法创建子控件

  {

   this.Controls.Add(new LiteralControl("<label>Sum</label>"));

   TextBox tb=new TextBox();

   tb.Text="";

   this.Controls.Add(tb);

   this.Controls.Add(new LiteralControl("<br>"));

  }

 }

编译该组件,并在工具箱中添加它

在asp.net web应用程序中添加两个文本框,一个标签和一个按钮,并拖放生成的控件,组成一个加法界面,在按钮点击事件中添加加法逻辑

执行程序测试可以看到控件生成的一个标签和一个文本框

自定义控件的使用范例

演示如何使用控件创建应用,使应用更利于维护

继续阅读