惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
IT之家
IT之家
Google DeepMind News
Google DeepMind News
罗磊的独立博客
爱范儿
爱范儿
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
U
Unit 42
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
B
Blog
博客园 - 叶小钗
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - nacarat

让UpdatePanel支持文件上传 使用ASP.NET AJAX的注意事项 使用ASP.NET AJAX实现幻灯片效果 提高网页打开速度的一些小技巧 ASP.NET AJAX(开发代号Atlas)重要参考资源大收集 如何生成静态页面的五种方案 ASP.NET验证控件祥解 全面了解 Cookie的传递流程、编程实现及安全问题 Asp.Net中虚拟文件系统的使用 如何彻底的做到代码和界面分离 用ASP.NET将原始图片按照指定大小按原始比例缩放显示图片 SQL注入详解 ASP.NET中如何防范SQL注入式攻击 学习ASP.NET比较完整的流程 如何在客户端获取上传图片的大小 观点:.NET发展中的几个失误 asp.net控件开发基础(4) JS代码的格式化和压缩 asp.net控件开发基础(3)
asp.net控件开发(2)
nacarat · 2008-04-15 · via 博客园 - nacarat

或许大家还对为何要重写Render方法存有疑惑,希望大家看看我举的例子,能够明白Render方法和其他两个方法的作用,然后真正明白为何一般情况下只须重写Render方法

我们知道我们每次编写控件时,都需要重写Render方法,我们发现在Control类中很多方法可以重写,但我们没有去重写他们,我们需要遵循一个原则,在需要重载的时候再去重写他们

我们还是先来看看与Render方法相关的两个方法

相信看过"ASP.NET服务器控件开发技术与实例"这本书的人,肯定看过上面的一段代码.

假设你不理解上面的流程(我也不一定理解,希望我的思路对你有帮助),我认为有一种很好的方式来理解上面的流程,跟大家分享一下.

现在抛开上面的代码,我们来建一个简单的页面,随意的拖几个控件到界面上,注意最后一个三panel控件,如下图


图一

我们知道,每个控件都有Visible和EnableViewState属性,Visible用来设置控件是否被呈现.

图二

现在我们把button控件的Visible属性设置为flase,我们看到了我们预期的效果,接着请启用页面跟踪,这个很重要

图三

在服务器上运行这个页面,大家可以在控件树上看到下面画面

图四

(1)System.Web.UI.LiteralControl

大家可以看到,在我们定义的每个控件之间都有System.Web.UI.LiteralControl.
这里需要说明的是,要理解任何不需要在服务器上处理的任何其他字符串.

如何理解呢?大家打开这个运行页面的源代码页面,如下代码,大家看到没有,除了服务器控件外,我们有其他元素(不需要在服务器上处理的任何其他字符串),包括空格.

示例一

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
  鏃犳爣棰橀〉
</title></head>
<body>
 
<form name="form1" method="post" action="Default1.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTExNTUxMDYxODdkZHVaWm47e5anDettRKviGvS0nDWQ" />
</div>

 
<div>
 
<span id="Label1">Label</span><br />
 
<br />
 
<input name="TextBox1" type="text" id="TextBox1" /><br />
 
<br />
 
<br />
 
<br />
 
<div id="Panel1" style="height:50px;width:125px;">
  
 
</div>
 
&nbsp;</div>
 
<div>

  
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgK/5/fTBwLs0bLrBrVw7YrSp5G/l4sJGPkKN/asFj2W" />
</div></form>
</body>
</html>

为了让大家更加明白System.Web.UI.LiteralControl的意思的,让我们来修改HTML页面,说明:以上代码为运行后的HTML源代码.而不是我们所说的源代码,大家应该明白我所指的源代码的意思.

我们来修改代码,注意:我把<form..以下的标签无空格的写在了一起.看下面修改后的代码

示例二

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" Trace="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
 
<title>无标题页</title>
</head>
<body>
 
<form id="form1" runat="server"><asp:Label ID="Label1" runat="server" Text="Label"></asp:Label><asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><asp:Button ID="Button1" runat="server" Text="Button" Visible="False" /><asp:Panel ID="Panel1" runat="server" Height="50px" Width="125px"></asp:Panel></form>
</body>
</html>

运行效果

图五

现在发现控件之间已经没有System.Web.UI.LiteralControl了,因为我去掉了空格.这个也说明了一点,如果代码很乱的话会影响速度.现在大家应该明白System.Web.UI.LiteralControl的意思了吧.

(2)大家继续看图四的Button1,大家会发现它呈现的大小字节数为0,因为我们设置了Button1的Visible值为False,所以未呈现此控件.

下面我们来理解这一点,大家重新看到RenderControl方法,如果Visible值为True则呈现此控件.

if(Visible)
 Render(writer);

为了理解这个方法,我们来重写此方法,我们以第一次讲的CreditCardForm3控件为例

我们重写RenderControl方法,把Render方法的代码全部拷贝到RenderControl方法中,然后去掉Render方法

然后在asp.net页面使用此控件,定义其Visible值为False

图六

运行这个例子以后,你会发现控件还是呈现了,就是因为你重写了RenderControl方法,使控件的Visible值无效了

所以我们就要加上一个判断

否则的话,此方法呈现的内容没有Visible值.为了更加深刻理解这一点,我们重写基类的RenderControl方法的方法.

base.RenderControl(writer);

你会发现在页面呈现时的控件有两个,一个在RenderControl方法方法输出,一个在Render方法输出,因为
base.RenderControl方法调用了Render方法,当设置控件Visible属性为False时,Render方法输出的内容被隐藏(未被呈现,而RenderControl方法输出的内容仍然存在.现在大家应该了解RenderControl方法的作用了吧.

如果服务器控件的 Visible 属性设置为 true,则向页呈现服务器控件的内容,所以一般情况下我们不重写此方法.因为一般控件都需要Visible 属性,除非特殊情况.

图七

(3)RenderChildren方法

再重新看到图四,大家可以看到,我们拖放的控件是在属于form1的子控件,panel控件是一个容器控件,因为下面没拖放控件,任何其他显示的字符串表现为System.Web.UI.LiteralControl,大家可以拖几个控件到panel里再重新运行看看,会发现拖进去的控件变为panel的子控件.最明显的的测试方法是Wizard控件,拖放一个Wizard控件然后再测试你就会明白了.

RenderChildren方法则判断当前控件是否有子控件,如果有,则根据RenderControl方法判断控件的Visible值来呈现控件.所以大家在重写Render方法时,不重写基类Render方法时,将无法实现RenderChildren方法.带来的后果将是无法呈现子控件.

下面我们来测试一下.我们还是以CreditCardForm3控件为例子(请先把RenderControl方法的内容全注释掉),当未重实现RenderChildren方法时则无法呈现子控件内容,请启动跟踪

将发现其子控件呈现字节为0

图八

由于CreditCardForm3继承了CreditCardForm2,所以重写基类Render方法将会重复输出,我们可以直接在Render方法中重写RenderChildren方法.再来测试.将会发现有些变化

发现其子控件呈现字节并非为0,而是10

图九

说明其子控件还是存在东西的,只不过没有用而已,所以大家可以根据实际需求来确实是否要重写RenderChildren方法,一般的话都会重写Render方法,这样保险一点

好了,现在再来回顾下刚开始给出的代码,通过上面的试验,你是否明白了?

呈现控件的步骤(注意:下面三个方法都可以呈现,不过我们已经说过了,像在RenderControl方法用HtmlTextWriter预先输出的话,就丧失Visible的功能(说不定你就不需要这个功能,那时你就可以重写这个方法了)

(1)RenderControl方法

先判断其Visible然后调用Render方法

(2) Render方法

使用HtmlTextWriter将标记字符和文本输出然后调用RenderChildren方法

(3)RenderChildren方法

判断当前控件是否有子控件,然后再调用RenderControl方法根据子控件的Visible值输出子控件.

我们了解上面三个方法后,就会知道,一般情况下,我们无须重写RenderControl方法和RenderChildren方法.所以最合适的就是重写Render方法了.说了一大堆.目的就是为了说明为什么要重写Render方法.

上次,忘了把代码传上了,不小心只上传了dll文件,不好意思.这次就写这么多.希望大家能够真正明白.大家可以适当的修改代码,这样你会发现更多.

参考文章:ASP.NET2.0服务器控件之Render方法