一、WebControl的呈现过程

WebControl派生自Control类,所以WebControl的呈现功能基于Control的呈现逻辑之上,但有了比较大的扩展。

首先,WebControl重写了Render(HtmlTextWriter writer)方法,将呈现的逻辑一分为三:RenderBeginTag()、RenderContents()、RenderEndTag()。WebControl的这种设计基于一种假设:每个WebControl最终生成一个HTML控件(当然这个HTML控件中可能还包含其他HTML子控件),所以WebControl的呈现过程就可分为:呈现开始标签、呈现标签中的内容和呈现结尾标签。

protected internal override void Render(HtmlTextWriter writer)

{

       this.RenderBeginTag(writer);

       this.RenderContents(writer);

       this.RenderEndTag(writer);

}

①呈现开始标签:

public virtual void RenderBeginTag(HtmlTextWriter writer)

{

    this.AddAttributesToRender(writer);

    HtmlTextWriterTag htmlTextWriterTag = this.TagKey;

    if (htmlTextWriterTag != HtmlTextWriterTag.Unknown)

    {

        writer.RenderBeginTag(htmlTextWriterTag);

        return;

    }

    writer.RenderBeginTag(this.TagName);

}

由上面的实现代码可知:RenderBeginTag()方法所生成的HTML标签是由WebControl.TagKey或WebControl.TagName属性决定的。

[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

protected virtual HtmlTextWriterTag TagKey

{

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]

    get

    {

        return this.tagKey;

    }

}

TagKey的类型为HtmlTextWriterTag 枚举,如果你的标签不在这个枚举中,则你需要把TagKey属性设为Unkown,并设置TagName属性,TagName属性为String类型,这意味着你可以将该属性设为任意值。

[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

protected virtual string TagName

{

    get

    {

         if (this.tagName == null && this.TagKey != HtmlTextWriterTag.Unknown)

         {

              this.tagName = Enum.Format(typeof(HtmlTextWriterTag), this.TagKey, "G").ToLower(CultureInfo.InvariantCulture);

         }

         return this.tagName;

     }

}

  • 注意:在通常情况下,我们不重写RenderBeginTag()方法,而通过重写TagKeyTagName属性来实现对生成的外围HTML标签的控制。

②呈现标签中的内容:

protected internal virtual void RenderContents(HtmlTextWriter writer)

{

    base.Render(writer);

}

③呈现结尾标签:

public virtual void RenderEndTag(HtmlTextWriter writer)

{

    writer.RenderEndTag();

}

到这里WebControl的呈现过程,都说完了,但有一个疑问是:最外围的HTML标签是怎么添加属性和样式属性的呢?

相信细心的同学一定发现在WebControl类RenderBeginTag()方法中第一行代码:

this.AddAttributesToRender(writer);

故名思议就是添加属性到呈现内容,我们看下该方法的实现:

protected virtual void AddAttributesToRender(HtmlTextWriter writer)

{

    if (this.ID != null)

    {

        writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);

    }

    if (this._webControlFlags[4])

    {

        string accessKey = this.AccessKey;

        if (accessKey.Length > 0)

        {

            writer.AddAttribute(HtmlTextWriterAttribute.Accesskey, accessKey);

        }

    }

    if (!this.Enabled)

    {

        if (this.SupportsDisabledAttribute)

        {

            writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");

        }

        if (this.RenderingCompatibility >= VersionUtil.Framework40 && !string.IsNullOrEmpty(WebControl.DisabledCssClass))

        {

            if (string.IsNullOrEmpty(this.CssClass))

            {

                this.ControlStyle.CssClass = WebControl.DisabledCssClass;

            }

            else

            {

                this.ControlStyle.CssClass = WebControl.DisabledCssClass + " " + this.CssClass;

            }

        }

    }

    if (this._webControlFlags[16])

    {

        int tabIndex = (int)this.TabIndex;

        if (tabIndex != 0)

        {

            writer.AddAttribute(HtmlTextWriterAttribute.Tabindex, tabIndex.ToString(NumberFormatInfo.InvariantInfo));

        }

    }

    if (this._webControlFlags[8])

    {

        string toolTip = this.ToolTip;

        if (toolTip.Length > 0)

        {

            writer.AddAttribute(HtmlTextWriterAttribute.Title, toolTip);

        }

    }

    if (this.TagKey == HtmlTextWriterTag.Span || this.TagKey == HtmlTextWriterTag.A)

    {

        this.AddDisplayInlineBlockIfNeeded(writer);

    }

    if (this.ControlStyleCreated && !this.ControlStyle.IsEmpty)

    {

        this.ControlStyle.AddAttributesToRender(writer, this);

    }

    if (this.attrState != null)

    {

        AttributeCollection attributes = this.Attributes;

        IEnumerator enumerator = attributes.Keys.GetEnumerator();

        while (enumerator.MoveNext())

        {

            string text = (string)enumerator.Current;

            writer.AddAttribute(text, attributes[text]);

        }

    }

}

首先,AddAttributesToRender()是一个虚方法,我们可以重写,又因为它在RenderBeginTag()开始时被调用,很显然我们可以将最外围的HTML标签添加属性和样式属性的逻辑在这里实现。其次,我们注意到WebControl类实现RenderBeginTag()方法时完成了(例如:Enabled与否,不同呈现)等基本的功能。所以在我们重写该方法为外围标签添加自定义属性和样式属性时,为了获得WebControl提供的基本功能。需在派生的控件类中调用父类的该方法:

protected override void AddAttributesToRender(HtmlTextWriter writer)

{

     base.AddAttributesToRender(writer);

     //......添加所需属性和样式的代码

}

二、从WebControl类派生"相册"控件

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;

namespace CustomServerControls

{

    public class Albumn : WebControl

    {

        //(一):WebControl默认TagKey为span,这里重写为Div

        protected override HtmlTextWriterTag TagKey

        {

            get

            {

                return HtmlTextWriterTag.Div;

            }

        }

        //(二:)为主标签(Div)添加一些样式属性

        protected override void AddAttributesToRender(HtmlTextWriter writer)

        {

            base.AddAttributesToRender(writer);

            writer.AddStyleAttribute(HtmlTextWriterStyle.TextAlign, "center");

            writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "194px");

            writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "194px");

            writer.AddStyleAttribute("background", "url(Images/background.gif) no-repeat left");

        }

        //(三):主标签的内容项是一个Img标签

        protected override void RenderContents(HtmlTextWriter writer)

        {

            writer.AddAttribute(HtmlTextWriterAttribute.Src, "Images/nature.jpg");

            writer.AddAttribute(HtmlTextWriterAttribute.Width, "160px");

            writer.AddAttribute(HtmlTextWriterAttribute.Height,"160px");

            writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "none");

            writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "0px");

            writer.AddStyleAttribute(HtmlTextWriterStyle.MarginTop, "16px");

            writer.RenderBeginTag(HtmlTextWriterTag.Img);

            writer.RenderEndTag();

        }

    }

}

第二篇:呈现内容_第二节:WebControl呈现的更多相关文章

  1. 第二篇:呈现内容_第一节:Control呈现

    一.Control的呈现过程 在上个章节““生死有序”的控件生命周期”中,我们提到Render是控件开发的主角,但在控件树的“合成模式(Composite)”部分这位主角却缺席了(戏份太多的缘由).哦 ...

  2. 第二篇:呈现内容_第三节:CompositeControl呈现

    一.CompositeControl的呈现过程 CompositeControl派生自WebControls,重写了Render(HtmlTextWriter writer)方法.在调用基类WebCo ...

  3. 第二篇 dom内容操作之value

    一.内容操作的三种方式 . 详情看第一篇 innerText innerHtml . value ==>表单类的标签 input >text passwd textarea . check ...

  4. 第二篇 Fiddler配置_浏览器&手机

    什么是Fiddler? 网络项目的开发和测试中,Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的 ,可以说是非常常用的手头工具了,本文就Fiddler使用和配置进行说明. ...

  5. Egret入门学习日记 --- 第二篇 (书籍的选择 && 书籍目录 && 书中 3.3 节 内容)

    第二篇 (书籍的选择 && 书籍目录 && 书中 3.3 节 内容) 既然选好了Egret,那我就要想想怎么学了. 开始第一步,先加个Q群先,这不,拿到了一本<E ...

  6. 【开源.NET】 轻量级内容管理框架Grissom.CMS(第二篇前后端交互数据结构分析)

    这是 CMS 框架系列文章的第二篇,第一篇开源了该框架的代码和简要介绍了框架的目的.作用和思想,这篇主要解析如何把sql 转成标准 xml 配置文件和把前端post的增删改数据规范成方便后台解析的结构 ...

  7. Matlab高级教程_第二篇:MATLAB和C#一些常用的矩阵运算方法的转换

    1.相关方法已经生产引用,直接调用的结果如下: 2. 相关调用代码如下: using System; using System.Collections.Generic; using System.Li ...

  8. Python开发【第二篇】:初识Python

    Python开发[第二篇]:初识Python   Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏 ...

  9. 第二篇 Replication:分发服务器的作用

    本篇文章是SQL Server Replication系列的第二篇,详细内容请参考原文. 分发服务器是SQL Server复制的核心组件.分发服务器控制并执行数据从一个服务器移动到另一个服务器的进程. ...

随机推荐

  1. 微软BI 之SSRS 系列 - 使用分组 Group 属性实现基于父子递归关系的汇总报表

    基于父子关系的递归结构在公司组织结构里比较常见,基本上都是在一张表里实现的自引用关系.在报表中如果要实现这种效果,并且在这个基础上做一些数据的汇总,可以使用到下面提到的方法. 要实现的效果大致如下 - ...

  2. C#实现U盘检查,并写入文件

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  3. LCD显示——点阵字体

    Bitmap font 点阵字体是把每一个字符都分成16×16或24×24个点,然后用每个点的虚实来表示字符的轮廓. 点阵字体优点是显示速度快,不像矢量字体需要计算:其最大的缺点是不能放大,一旦放大后 ...

  4. IDEA中Gradle插件的使用

    Idea本身已经集成了Gradle插件,你可以在File | Settings | Build, Execution, Deployment | Build Tools | Gradle 下找到 相关 ...

  5. ADHOC Report 配置

    ADHOC Report ADHOC Report - 临时的report,随时可以去系统中按照你选择的条件打出你想看的report Add ADHOC Report --AddReport use ...

  6. HDFS之FileStatus

    任何文件系统的一个重要特性都是提供其目录结构浏览和检索它所存文件和目录相关信息的功能.FileStatus对象封装了文件系统中文件和目录的元数据,包括文件的长度.块大小.备份数.修改时间.所有者以及权 ...

  7. golang之tcp自动重连

    操作系统: CentOS 6.9_x64 go语言版本: 1.8.3 问题描述 现有一个tcp客户端程序,需定期从服务器取数据,但由于种种原因(网络不稳定等)需要自动重连. 测试服务器示例代码: /* ...

  8. Servlet简介与生命周期

    一:Servlet是什么 Servlet是运行在Web服务器上的Java程序,作为处理来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层.JSP在w ...

  9. excel合并同类项去重求和功能

    参考:百度经验 主要利用函数为:sumif(range,criteria,[sum_range]) Range:条件区域,用于条件判断的单元格区域. Criteria:求和条件,由数字.逻辑表达式等组 ...

  10. Linux人工清理内存cache

     内存缓存的出现是解决,设备之间的读写速度的差异! 00.linux缓存解释 /proc/sys/vm/drop_caches (since Linux 2.6.16)Writing to this ...