在 ASP.NET 中 Label 控件在输出到客户端时是一个 span 控件,ListBox 输出到客户端时是一个 select 控件,BulletedList 输出到客户端时是一个 ul 控件……
也就是说 ASP.NET 的控件和 HTML 控件存在一定的联系,那么我可不可以更改这种联系呢?比如我要把 ASP.NET 中的 Label 控件与 HTML 中的 div 控件对应起来,可不可以呢?
可以的,这就是本节要讨论的内容,我们以 BulletedList 为例,我们不希望 BulletedList 输出的是 ul 列表,而是一项一个段落 p 的形式,这里就不要讨论输出 ul 好还是输出 p 好。
首先
我们要建立一个 class 放在 App_Code 文件夹中,这个类的作用就是重写 ASP.NET 控件到 HTML 控件的转换,该类代码如下:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls.Adapters;
namespace Cftea
{
public class BulletedListAdapter : WebControlAdapter
{
protected override void RenderBeginTag(HtmlTextWriter writer)
{
//base.RenderBeginTag(writer);
}
protected override void RenderContents(HtmlTextWriter writer)
{
BulletedList bl = Control as BulletedList;
if (bl != null)
{
int i = 0;
for (i = 0; i < bl.Items.Count; i++)
{
writer.WriteBeginTag("p");
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(bl.Items[i].Text);
writer.WriteEndTag("p");
}
}
//base.RenderContents(writer);
}
protected override void RenderEndTag(HtmlTextWriter writer)
{
//base.RenderEndTag(writer);
}
}
}
- 类名随便起,但该类要继承于 WebControlAdapter,WebControlAdapter 的名称空间是 System.Web.UI.WebControls.Adapters。
- 重载三个函数:RenderBeginTag,RenderContents,RenderEndTag。
- 由于我们要全部重写 BulletedList 的输出,所以要在这三个函数中去掉对父类的调用,即程序中注释掉的部分。
- p 和 ul 不一样,p 是一个项目一个,而 ul 下一级还需要 li,所以我们只需要在 RenderContents 中增加内容。
- BulletedList bl = Control as BulletedList; as 用于在兼容的引用类型之间执行转换,详情参见 MSDN 的 as(C#),Control 也即要转换的控件。
- writer.WriteBeginTag("p"); 写开始标签,自动添加“<”。
- writer.Write(HtmlTextWriter.TagRightChar); 写“>”,由于 WriteBeginTag 不会自动添加“>”,所以这里要手动写“>”。
- writer.Write(bl.Items[i].Text); 写每一个 item 的文字。
- writer.WriteEndTag("p"); 写结束标签,自动添加“<”和“>”。
然后
重载类已经写好了,放在 App_Code 目录下,但还需要进一步设置才有效。
新建一个 App_Browsers 文件夹,再新建一个 browser 文件,同样文件名并不重要(似乎放在 ASP.NET 文件夹(诸如:App_Browsers、App_Code、App_Themes、bin)下面的文件,其文件名都不重要,重要的是标识、ID、名称空间,并且 ASP.NET 会自动查找、自动更新,应用起来方便得不得了。)
browser 文件的代码如下:
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.BulletedList"
adapterType="Cftea.BulletedListAdapter"></adapter>
</controlAdapters>
</browser>
</browsers>
- <browser refID="Default"> refID="Default" 表示对于所有的浏览器都应用其 controlAdapters。
- adapter 的 controlType 表示要转换哪一类控件。
- adapter 的 adapterType 格式为“名称空间 + 类名”,表示 controlType 交由 adapterType 指示的类处理。
完成
此时我们再在 .aspx 中添加一个 BulletedList,输出时,就不再是 ul,而是 p 了。
利用适配器,我们可以把 ASP.NET 的控件映射到 HTML 中的某一类控件,也可以映射到一类我们自己设计的“控件”,比如带选择框的下拉列表框。
我们还将在后面的连载中具体讲解本节步骤的两点内容,尤其是第二点,可以根据不同的浏览器对控件进行不同的转换。
说明
上面 WriteBeginTag 更好的做法是使用 RenderBeginTag;而 "p" 也使用 HtmlTextWriterTag.P;WriteEndTag("p") 使用 RenderEndTag() 自动匹配。