11.2 自定义控件
用户控件能够执行很多操作。并实现一些功能,但是在复杂的环境下,用户控件并不能够达到开发人员的要求,是因为用户控件大部分都是使用现有的控件进行组装,编写事件来达到目的。于是,ASP.NET允许开发人员编写自定义控件实现复杂的功能。
11.2.1 实现自定义控件
自定义控件与用户控件不同,自定义控件需要定义一个直接或间接从Control类派生的类,并重写Render方法。在.NET框架中,System.Web.UI.Control与System.Web.UI.WebControls.WebControl两个类是服务器控件的基类,并且定义了所有服务器控件共有的属性、方法和事件,其中最为重要的就是包括了控制控件执行生命周期的方法和事件,以及ID等共有属性。
实现自定义控件,必须创建一个自定义控件,自定义控件将会编译成DLL文件。创建自定义控件如图11-7所示。
图11-7 创建自定义控件
自定义控件创建完成后,会自动生成一个类,并在类中生成相应的方法,示例代码如下所示。
开发人员可以在源代码中编写和添加属性。当需要呈现给HTML页面输出时,只需要重写Render方法即可,示例代码如下所示。
在使用服务器控件时,会发现控件有很多的属性,例如SqlConnection属性、Color属性等,如图11-8所示。
图11-8 控件的属性
为了实现服务器控件的智能属性配置,开发人员能够在源代码中编写属性,示例代码如下所示。
当自定义控件编写完毕后,需要在需要使用该控件的项目中添加引用。右击现有项目,选择【添加引用】选项,如果是同在一个解决方案下,则只要选择【项目】选项卡即可。而如果不在同一解决方案,则需要选择【浏览】选项卡浏览相应的DLL文件,如图11-9和图11-10所示。
图11-9 添加项目引用
图11-10 浏览DLL
单击【确定】按钮完成引用的添加后,就可以在页面中使用此自定义控件。若需要在页面中需要使用此自定义控件,同样同用户控件一样需要在头部声明自定义控件,示例代码如下所示。
上述代码向页面注册了自定义控件,自定义注册完毕后,就能够在页面中使用该控件。同时,在工具栏中也会呈现自定义控件,如图11-11所示。自定义控件呈现在工具箱之后,就可以直接拖动自定义控件到页面,并且配置相应的属性,如图11-12所示。
图11-11 呈现自定义控件
图11-12 配置自定义属性
正如图11-12所示,开发人员能够在自定义控件中编写属性,这些属性可以是共有属性也可以是用户自定义的属性,用户可以拖动自定义控件使用于自己的应用程序中并通过属性进行自定义控件的配置。用户拖动自定义页面到控件后,页面会生成相应的自定义控件的HTML代码,示例代码如下所示。
上述代码就在页面中使用了自定义控件。在ASP.NET服务器控件中,很多的控件都是通过自定义控件来实现的,开发人员能够开发相应的自定义控件并在不同的应用中使用而无需重复开发。
11.2.2 复合自定义控件
单单一个简单的控件并不能实现太多的效果,在实际开发中,可能需要更多的功能,这种复杂功能控件最常见的就是SqlDataSource控件。SqlDataSource控件是数据源控件,通过SqlDataSource控件能够配置数据源,并且实现分页、插入、删除等功能。复合自定义控件就类似这样一个功能复杂的控件。编写复合自定义控件有以下几种方式:
1)创建用户控件,并使用用户控件封装的用户界面实现复合控件。
2)开发一个编译控件,封装一个按钮控件和文本框控件,通过重写Render方法呈现。
3)从现有的控件中派生出新控件。
4)从基本控件类之一派生来创建自定义控件。
通过编写复合控件,能够让控件开发更加灵活,控件的使用人员也能够更加方便的配置控件,例如,重写登录控件,前台页面制作人员使用该控件时,可以为控件配置验证等功能,方便前台人员配置和使用。如图11-13所示。
图11-13 登录控件
为了实现登录控件,就必须在自定义控件中添加相应的服务器控件,在登录控件中,需要两个TextBox来让用户输入用户名和密码,填写完成后,必须单击登录按钮实现登录事件。在类中创建TextBox和Button代码如下所示。
上述代码创建了两个TextBox控件和一个Button控件。其中,NameTextBox让用户能够输入用户名,而PasswordTextBox能够让用户输入密码。当用户单击LoginButton时,就需要实现登录操作,在这里就需要声明一个事件,示例代码如下所示。
完成对控件和事件的声明,就需要进行属性的编写。在登录控件中,希望在前台开发人员在开发过程中,能够轻易的配置属性进行使用,从而提高代码的复用性。在图11-13所表示控件中,开发人员希望控件的使用人员能够配置背景颜色、边框粗细、内置距离、登录说明和跳转连接等。在代码中,可以分别为这些属性进行配置,示例代码如下所示。
上述代码定义了一个属性,在属性定义前,可以对属性进行描述,如代码中Bindable、Category等,这些常用的描述意义如下所示:
1)Bindable:是否用于绑定。
2)Category:属性或事件显示在一个设置为“按分类顺序”的模式,如果不指定,则会显示在杂项中。
3)DefaultValue:指定属性的默认值。
4)Localizable:指定属性是否本地化。
编辑相应属性,在属性配置中就能够做相应的配置,如图11-14所示。
图11-14 自定义属性
在代码中,将Category属性设置为Appearance,这个属性就会在【外观】选项卡中出现。配置完成LoginBackGroundColor后,就可以为其他的属性做相应的配置,示例代码如下所示。
编写完成属性后,就可以通过重写Render方法呈现不同的HTML,示例代码如下所示。
上述代码使用了HtmlTextWriter类,HtmlTextWriter类能够动态的创建HTML标签。上述代码中使用了HtmlTextWriter类的对象的RenderBeginTag方法创建相应的HTML标记。重写Render方法以呈现不同的HTML后,用户就能够看到登录界面,当用户单击【登录】按钮后,应该执行登录事件,这里应该是个事件冒泡,编写按钮提交事件代码如下所示。
编写按钮事件后,整个自定义控件就制作完毕了。相比之下,自定义控件的制作并不是那么难,反而自定义控件能够实现更多的效果,并呈现不同的样式,并且允许界面开发人员能够通过相应的配置呈现不同的样式。
11.2.1 实现自定义控件
自定义控件与用户控件不同,自定义控件需要定义一个直接或间接从Control类派生的类,并重写Render方法。在.NET框架中,System.Web.UI.Control与System.Web.UI.WebControls.WebControl两个类是服务器控件的基类,并且定义了所有服务器控件共有的属性、方法和事件,其中最为重要的就是包括了控制控件执行生命周期的方法和事件,以及ID等共有属性。
实现自定义控件,必须创建一个自定义控件,自定义控件将会编译成DLL文件。创建自定义控件如图11-7所示。
图11-7 创建自定义控件
自定义控件创建完成后,会自动生成一个类,并在类中生成相应的方法,示例代码如下所示。
+展开
-C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;//使用UI命名空间以便继承
namespace ServerControl1
{
[DefaultProperty("Text")]//声明属性
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]//设置控件格式
public class ServerControl1 : WebControl
{
[Bindable(true)]设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string Text//定义Text属性
{
get //获取属性
{
String s = (String)ViewState["Text"];//获取属性的值
return ((s == null) ? "[" + this.ID + "]" : s);//返回默认的属性的值
}
set //设置属性
{
ViewState["Text"] = value;
}
}
protected override void RenderContents(HtmlTextWriter output)//页面呈现
{
output.Write(Text);
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;//使用UI命名空间以便继承
namespace ServerControl1
{
[DefaultProperty("Text")]//声明属性
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]//设置控件格式
public class ServerControl1 : WebControl
{
[Bindable(true)]设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string Text//定义Text属性
{
get //获取属性
{
String s = (String)ViewState["Text"];//获取属性的值
return ((s == null) ? "[" + this.ID + "]" : s);//返回默认的属性的值
}
set //设置属性
{
ViewState["Text"] = value;
}
}
protected override void RenderContents(HtmlTextWriter output)//页面呈现
{
output.Write(Text);
}
}
}
开发人员可以在源代码中编写和添加属性。当需要呈现给HTML页面输出时,只需要重写Render方法即可,示例代码如下所示。
+展开
-C#
protected override void RenderContents(HtmlTextWriter output)
{
output.Write("定义的Text属性的值为:" + Text);//输出为页面呈现
}
{
output.Write("定义的Text属性的值为:" + Text);//输出为页面呈现
}
在使用服务器控件时,会发现控件有很多的属性,例如SqlConnection属性、Color属性等,如图11-8所示。
图11-8 控件的属性
为了实现服务器控件的智能属性配置,开发人员能够在源代码中编写属性,示例代码如下所示。
+展开
-C#
public string GuoJingString//编写属性
{
get { return (String)ViewState["GuoJingString"]; }//获取属性
set { ViewState["GuoJingString"] = value; }//设置属性
}
{
get { return (String)ViewState["GuoJingString"]; }//获取属性
set { ViewState["GuoJingString"] = value; }//设置属性
}
当自定义控件编写完毕后,需要在需要使用该控件的项目中添加引用。右击现有项目,选择【添加引用】选项,如果是同在一个解决方案下,则只要选择【项目】选项卡即可。而如果不在同一解决方案,则需要选择【浏览】选项卡浏览相应的DLL文件,如图11-9和图11-10所示。
图11-9 添加项目引用
图11-10 浏览DLL
单击【确定】按钮完成引用的添加后,就可以在页面中使用此自定义控件。若需要在页面中需要使用此自定义控件,同样同用户控件一样需要在头部声明自定义控件,示例代码如下所示。
+展开
-HTML
<%@ Register TagPrefix="MyControl" Namespace="ServerControl1" Assembly="ServerControl1" %>
上述代码向页面注册了自定义控件,自定义注册完毕后,就能够在页面中使用该控件。同时,在工具栏中也会呈现自定义控件,如图11-11所示。自定义控件呈现在工具箱之后,就可以直接拖动自定义控件到页面,并且配置相应的属性,如图11-12所示。
图11-11 呈现自定义控件
图11-12 配置自定义属性
正如图11-12所示,开发人员能够在自定义控件中编写属性,这些属性可以是共有属性也可以是用户自定义的属性,用户可以拖动自定义控件使用于自己的应用程序中并通过属性进行自定义控件的配置。用户拖动自定义页面到控件后,页面会生成相应的自定义控件的HTML代码,示例代码如下所示。
+展开
-HTML
<form id="form1" runat="server">
<div>
<MyControl:ServerControl1 ID="ServerControl11" runat="server" />
</div>
</form>
<div>
<MyControl:ServerControl1 ID="ServerControl11" runat="server" />
</div>
</form>
上述代码就在页面中使用了自定义控件。在ASP.NET服务器控件中,很多的控件都是通过自定义控件来实现的,开发人员能够开发相应的自定义控件并在不同的应用中使用而无需重复开发。
11.2.2 复合自定义控件
单单一个简单的控件并不能实现太多的效果,在实际开发中,可能需要更多的功能,这种复杂功能控件最常见的就是SqlDataSource控件。SqlDataSource控件是数据源控件,通过SqlDataSource控件能够配置数据源,并且实现分页、插入、删除等功能。复合自定义控件就类似这样一个功能复杂的控件。编写复合自定义控件有以下几种方式:
1)创建用户控件,并使用用户控件封装的用户界面实现复合控件。
2)开发一个编译控件,封装一个按钮控件和文本框控件,通过重写Render方法呈现。
3)从现有的控件中派生出新控件。
4)从基本控件类之一派生来创建自定义控件。
通过编写复合控件,能够让控件开发更加灵活,控件的使用人员也能够更加方便的配置控件,例如,重写登录控件,前台页面制作人员使用该控件时,可以为控件配置验证等功能,方便前台人员配置和使用。如图11-13所示。
图11-13 登录控件
为了实现登录控件,就必须在自定义控件中添加相应的服务器控件,在登录控件中,需要两个TextBox来让用户输入用户名和密码,填写完成后,必须单击登录按钮实现登录事件。在类中创建TextBox和Button代码如下所示。
+展开
-C#
public class ServerControl1 : WebControl
{//创建服务器控件
public TextBox NameTextBox = new TextBox();//创建TextBox控件
public TextBox PasswordTextBox = new TextBox(); //创建密码控件
public Button LoginButton = new Button();//创建Button控件
//…
//…
}
{//创建服务器控件
public TextBox NameTextBox = new TextBox();//创建TextBox控件
public TextBox PasswordTextBox = new TextBox(); //创建密码控件
public Button LoginButton = new Button();//创建Button控件
//…
//…
}
上述代码创建了两个TextBox控件和一个Button控件。其中,NameTextBox让用户能够输入用户名,而PasswordTextBox能够让用户输入密码。当用户单击LoginButton时,就需要实现登录操作,在这里就需要声明一个事件,示例代码如下所示。
+展开
-C#
public event EventHandler LoginClick;//声明事件
完成对控件和事件的声明,就需要进行属性的编写。在登录控件中,希望在前台开发人员在开发过程中,能够轻易的配置属性进行使用,从而提高代码的复用性。在图11-13所表示控件中,开发人员希望控件的使用人员能够配置背景颜色、边框粗细、内置距离、登录说明和跳转连接等。在代码中,可以分别为这些属性进行配置,示例代码如下所示。
+展开
-C#
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoignBackGroundColor//设置背景属性
{
get { return (String)ViewState["LoignBackGroundColor"]; }//获取背景
set { ViewState["LoignBackGroundColor"] = value; }//设置背景
}
[Category("Appearance")]设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoignBackGroundColor//设置背景属性
{
get { return (String)ViewState["LoignBackGroundColor"]; }//获取背景
set { ViewState["LoignBackGroundColor"] = value; }//设置背景
}
上述代码定义了一个属性,在属性定义前,可以对属性进行描述,如代码中Bindable、Category等,这些常用的描述意义如下所示:
1)Bindable:是否用于绑定。
2)Category:属性或事件显示在一个设置为“按分类顺序”的模式,如果不指定,则会显示在杂项中。
3)DefaultValue:指定属性的默认值。
4)Localizable:指定属性是否本地化。
编辑相应属性,在属性配置中就能够做相应的配置,如图11-14所示。
图11-14 自定义属性
在代码中,将Category属性设置为Appearance,这个属性就会在【外观】选项卡中出现。配置完成LoginBackGroundColor后,就可以为其他的属性做相应的配置,示例代码如下所示。
+展开
-C#
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoignBackGroundColor//设置背景颜色
{
get { return (String)ViewState["LoignBackGroundColor"]; }//获取属性的值
set { ViewState["LoignBackGroundColor"] = value; }//设置属性默认值
}
//登录边框粗细
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoginBorderWidth//设置边框粗细
{
get { return (String)ViewState["LoginBorderWidth"]; }//获取边框属性的值
set { ViewState["LoginBorderWidth"] = value; }//设置边框默认值
}
//登录的内置距离
[Bindable(true)] //设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoginPadding//设置内置距离
{
get { return (String)ViewState["LoginPadding"]; }//获取内置距离的值
set { ViewState["LoginPadding"] = value; }//设置默认值
}
//登录说明
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoginInformation//设置登录信息
{
get { return (String)ViewState["LoginInformation"]; }//获取登录信息的值
set { ViewState["LoginInformation"] = value; }//设置默认登录信息值
}
//登录跳转URL
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string ResignURL//设置登录跳转URL
{
get { return (String)ViewState["ResignURL"]; }//获取URL的值
set { ViewState["ResignURL"] = value; }//设置URL默认值
}
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoignBackGroundColor//设置背景颜色
{
get { return (String)ViewState["LoignBackGroundColor"]; }//获取属性的值
set { ViewState["LoignBackGroundColor"] = value; }//设置属性默认值
}
//登录边框粗细
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoginBorderWidth//设置边框粗细
{
get { return (String)ViewState["LoginBorderWidth"]; }//获取边框属性的值
set { ViewState["LoginBorderWidth"] = value; }//设置边框默认值
}
//登录的内置距离
[Bindable(true)] //设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoginPadding//设置内置距离
{
get { return (String)ViewState["LoginPadding"]; }//获取内置距离的值
set { ViewState["LoginPadding"] = value; }//设置默认值
}
//登录说明
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string LoginInformation//设置登录信息
{
get { return (String)ViewState["LoginInformation"]; }//获取登录信息的值
set { ViewState["LoginInformation"] = value; }//设置默认登录信息值
}
//登录跳转URL
[Bindable(true)]//设置是否支持绑定
[Category("Appearance")]//设置类别
[DefaultValue("")]//设置默认值
[Localizable(true)]//设置是否支持本地化操作
public string ResignURL//设置登录跳转URL
{
get { return (String)ViewState["ResignURL"]; }//获取URL的值
set { ViewState["ResignURL"] = value; }//设置URL默认值
}
编写完成属性后,就可以通过重写Render方法呈现不同的HTML,示例代码如下所示。
+展开
-C#
protected override void RenderContents(HtmlTextWriter output)//编写页面输出
{
output.RenderBeginTag(HtmlTextWriterTag.Div);//创建Div标签
output.RenderBeginTag(HtmlTextWriterTag.Tr); //创建Tr标签
NameTextBox.RenderControl(output);//添加控件
output.RenderBeginTag(HtmlTextWriterTag.Td);//创建Td标签
output.RenderBeginTag(HtmlTextWriterTag.Br);//创建Br标签
output.RenderBeginTag(HtmlTextWriterTag.Tr);//创建Tr标签
PasswordTextBox.RenderControl(output);//添加控件
output.RenderBeginTag(HtmlTextWriterTag.Td); //输出Td标签
}
{
output.RenderBeginTag(HtmlTextWriterTag.Div);//创建Div标签
output.RenderBeginTag(HtmlTextWriterTag.Tr); //创建Tr标签
NameTextBox.RenderControl(output);//添加控件
output.RenderBeginTag(HtmlTextWriterTag.Td);//创建Td标签
output.RenderBeginTag(HtmlTextWriterTag.Br);//创建Br标签
output.RenderBeginTag(HtmlTextWriterTag.Tr);//创建Tr标签
PasswordTextBox.RenderControl(output);//添加控件
output.RenderBeginTag(HtmlTextWriterTag.Td); //输出Td标签
}
上述代码使用了HtmlTextWriter类,HtmlTextWriter类能够动态的创建HTML标签。上述代码中使用了HtmlTextWriter类的对象的RenderBeginTag方法创建相应的HTML标记。重写Render方法以呈现不同的HTML后,用户就能够看到登录界面,当用户单击【登录】按钮后,应该执行登录事件,这里应该是个事件冒泡,编写按钮提交事件代码如下所示。
+展开
-C#
public void Submit_Click(object sender, EventArgs e)
{
EventArgs arg = new EventArgs();//编写按钮事件方法
if (LoginClick != null)//判断事件冒泡是否为空
{
LoginClick(LoginButton, arg);//触发事件
}
}
{
EventArgs arg = new EventArgs();//编写按钮事件方法
if (LoginClick != null)//判断事件冒泡是否为空
{
LoginClick(LoginButton, arg);//触发事件
}
}
编写按钮事件后,整个自定义控件就制作完毕了。相比之下,自定义控件的制作并不是那么难,反而自定义控件能够实现更多的效果,并呈现不同的样式,并且允许界面开发人员能够通过相应的配置呈现不同的样式。
加支付宝好友偷能量挖...