实际开发Asp.NET应用时,有时会想要将一些有复用价值的代码封装为Web控件的需求。下面以TabControl控件的制作为例,介绍一下整个开发过程,包含UI部分的渲染以及事件的上传等机制的实现方式。
1.项目选择
首先是项目选择,你应该选择生成ASP.NET服务器控件。选择此种项目类型后,集成开发环境会为你生成一些代码,最重要的函数是这个:
“protected override void RenderContents(HtmlTextWriter output)”
这个函数向输出流中输出最终的Html代码。注意,因为输出的是发往客户端的html代码,所以,这里不应该出现服务器端控件的信息。
2.主体渲染代码:
主体渲染代码打算用<Img>控件来实现Tab选项卡的效果。基本原理是这样的:
<html>
<body>
<table width="100%" cellpadding="0" cellspacing = "0" border="0">
<tr>
<td width="1%">
<img src="resource/tab_item.png" width="150px" height="45"/>
</td>
<td width="1%">
<img src="resource/tab_item_select.png" width="150px" height="45"/>
</td>
<td width="97%">
</td>
<td width="1%">
<img src="resource/tab_item.png" width="150px" height="45"/>
</td>
</tr>
<tr>
<td colspan="5">
<img src="resource/bar_vertical_line.png" width="100%" height="15"/>
</td>
</tr>
</table>
</body>
</html>
使用三幅图:一幅是选中的Tab卡;一幅是未选中的Tab卡,一幅是Tab卡下面的长条Bar.
3.传入参数的处理
仿照项目启动时的示例代码,创建多个输入参数
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string ImgItem
{
get
{
return (String)ViewState["ImgItem"];
}
set
{
ViewState["ImgItem"] = value;
}
}
4.资源文件的处理
使用ResolveUrl,将用户端的输入文件转换为客户端可以使用的相对路径。
5.事件的处理
TabControl中需要处理Tab标签的点击事件,我们最终的目标是将这个点击事件由控件的自定义Event...OnTabPageChanged传送出去,为此我们需要做如下步骤:
5.1)自定义外部事件
public event EventHandler OnTabPageChanged
{
add
{
Events.AddHandler(this, value);
}
remove
{
Events.RemoveHandler(this, value);
}
}
5.2)类增加IPostBackEventHandler接口,并增加函数:
public void RaisePostBackEvent(string eventArgument)
{
int idx;
if (int.TryParse(eventArgument, out idx))
{
CurrentTabItem = idx;
EventHandler eh = (EventHandler)Events[this];
if (eh != null)
{
eh(this, new EventArgs());
}
}
}
这里是定义了控件的消息捕获函数,对eventArgument为一个整数的消息做了处理,将这个消息与外部事件绑定到一起。
5.3)激发事件的处理:
sb.AppendFormat("<Image src=\"{0}\" width=\"{1}\" height=\"{2}\"
οnclick=\"javascript:__doPostBack('{4}','{3}');\"/>",
ResolveUrl(ImgSelectedItem), WidthItem, HeightItem,
id, this.ClientID);
注意其中的onclick事件, ClientID, id部分。
id是一个整形变量,对应着一个tab页面,上述代码实际上是RenderContents中创建一个Tab选项卡的部分代码。注意事件挂接部分,上面onclick的部分是硬编码到事件发送,实际编码时最好选用系统封装好的事件触发方法:Page.ClientScript.GetPostBackEventReference(object Control, string param);否则在某种特殊的使用场合,控件的消息激发机制可能不起作用,比如在母版页中使用该控件。
6.外部调用
你首先需要在Web应用程序中添加WebControl所在类库的引用。然后,你可能还需要把这个自定义控件添加进工具箱,然后就是一些配置,实际用法和标准的服务器控件是完全一样的。最终的显示效果如下图所示(未经过美工处理):