第二篇:呈现内容_第二节:WebControl呈现

简介:

一、WebControl的呈现过程

clipboard

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();
        }
    }
}
作者: 韩兆新
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

本文转自韩兆新博客博客园博客,原文链接:http://www.cnblogs.com/hanzhaoxin/p/4055422.html,如需转载请自行联系原作者
目录
相关文章
|
3月前
|
C# 开发者 数据处理
WPF开发者必备秘籍:深度解析数据网格最佳实践,轻松玩转数据展示与编辑大揭秘!
【8月更文挑战第31天】数据网格控件是WPF应用程序中展示和编辑数据的关键组件,提供排序、筛选等功能,显著提升用户体验。本文探讨WPF中数据网格的最佳实践,通过DevExpress DataGrid示例介绍其集成方法,包括添加引用、定义数据模型及XAML配置。通过遵循数据绑定、性能优化、自定义列等最佳实践,可大幅提升数据处理效率和用户体验。
60 0
|
5月前
|
编解码 前端开发 JavaScript
带您一步步构建一个基本的动态新闻网站,包括页面布局、样式设计以及交互效果的实现
【6月更文挑战第14天】构建动态新闻网站实战项目,涉及页面布局、样式设计和交互实现。首页采用顶部导航栏、轮播图和新闻列表布局;新闻列表页按分类显示新闻,详情页展示完整内容并可添加相关推荐和评论。设计注重色彩搭配、字体选择和布局间距,实现轮播图效果、导航栏交互和响应式设计,提升用户体验。该项目有助于锻炼HTML和CSS技能,理解网页设计实际应用。
130 1
|
前端开发
|
前端开发
前端学习案例4-瀑布流方式4
前端学习案例4-瀑布流方式4
71 0
前端学习案例4-瀑布流方式4
|
前端开发
前端学习案例1-瀑布流方式1
前端学习案例1-瀑布流方式1
84 0
前端学习案例1-瀑布流方式1
|
前端开发
前端学习案例3-瀑布流方式3
前端学习案例3-瀑布流方式3
59 0
前端学习案例3-瀑布流方式3
|
前端开发
前端学习案例2-瀑布流方式2
前端学习案例2-瀑布流方式2
64 0
前端学习案例2-瀑布流方式2
|
前端开发 搜索推荐 索引
重学前端 5 # 如何运用语义类标签来呈现Wiki网页?
重学前端 5 # 如何运用语义类标签来呈现Wiki网页?
120 0
重学前端 5 # 如何运用语义类标签来呈现Wiki网页?
|
前端开发
第34/90步《前端篇》第8章 重构记分板、背景、页面和游戏对象 第25课
今天学习《前端篇》第8章 重构记分板、背景、页面和游戏对象 第25课 重构游戏对象,这节课我们继续模块化重构,将页面类拆分到单独的文件中,清除一些不再需要的变量等,让游戏代码的结构更加合理。
66 0
|
前端开发
第33/90步《前端篇》第8章 重构记分板、背景、页面和游戏对象 第24课
今天学习《前端篇》第8章 重构记分板、背景、页面和游戏对象 第24课 创建页面对象,这节课开始创建游戏页面。
72 0