控件适配器-初步

作者:vkvi 来源:ITPOW(原创) 日期:2007-11-14

在 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() 自动匹配。

相关文章