posted @ 2008-07-28 10:35 李炉烽 阅读(111) 评论(0) 编辑
或许大家还对为何要重写Render方法存有疑惑,希望大家看看我举的例子,能够明白Render方法和其他两个方法的作用,然后真正明白为何一般情况下只须重写Render方法

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

我们还是先来看看与Render方法相关的两个方法
//RenderControl方法的基本实现
 public void RenderControl(HtmlTextWriter writer)
 
{
 
if(Visible)
 
{
 Render(writer);
 }

 }

 
//Render方法基本实现
 protected virtual void Render(HtmlTextWriter writer)
 
{
 RenderChildren(writer);
 }

 
//RenderChildren方式基本实现
 protected virtual void RenderChildren(HtmlTextWriter writer)
 
{
 
foreach (Control c in Controls)
 
{
 c.RenderControl(writer);
 }

 }

相信看过"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值无效了

所以我们就要加上一个判断
if(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方法
posted @ 2008-07-28 10:28 李炉烽 阅读(109) 评论(0) 编辑


2008/6/28 上午 12:50:00

很抱歉,本站不歡迎來自 [百度] (Baidu.com) 的訪客 !!

543 | 不爽 | 技術隨筆

沒什麼特別的,只是針對這次的盜文事件,我很不滿意百度 (Baidu.com) 的處理方式而以。

幾個月前曾發生過 BLOGGER.COM 有人直接把我的文章一字不漏的貼在他的 BLOG 上,沒有標示文章出處,最後用我破破的英文跟 GOOGLE 反映之後,GOOGLE 立即作了處理,關閉那位使用者的網頁

這次碰到類似的情況,有耐心的人就聽我講完這無聊的故事吧。無意間我在對岸的入口網站 [百度知道] (類似奇摩知識+的網站),發現有人拿我的文章,一字不漏的貼上去回答問題賺點數,一樣沒有標示文章出處,感到非常的不滿,馬上註冊了帳號,留下回應表示該文侵犯了我的權益,要求引用文章要註明出處,同時也跟站方反應了這個情況,要求站方作妥善的處理。

原本以為事情會像上次一樣,跟 GOOGLE 一樣的處理方式結束。沒料到...

  1. 隔天,發現我的留言被刪了? 嗯... 再補一次。
  2. 跟站方反應的結果? 竟然說這個不尊重智財權的使用者沒有違反規定???? 所以不做任何處理。
  3. 另一方面,留言留了不斷的被刪除,到現在已經被刪了第五次了,第六次的留言不知道會留到什麼時後...。

很無聊的戲就這樣一直演下去... 就是不斷的抗議又被刪除,跟站方反應卻又不理睬...。看來小蝦米是對抗不了大鯨魚的,也只能這樣了。其實我除了文章被盜貼之外沒有什麼具體的損失,就是心理很不爽而以,而更離譜的是百度站方處理的態度...。

資訊隨手可得,不代表資訊是可以任意踐踏的。免費的資訊,不用付費不代表就不需要尊重,也許對岸還有很多使用者沒建立起這樣的觀念,但是百度站方的處理方式也令我跌破眼鏡,有這樣的站方難怪會縱容這樣的使用者... :@

身為渺小不起眼 BLOG 主人,我也只能用消極的抗議,來表示我的不滿。除了寫這篇文章以外,也順帶來個 ASP.NET HttpModule 教學...。針對這次事件,我特地在本站加上了這個 HttpModule,只要查出使用者是透過任何由百度提供的 LINK 而連到本站的話,都會顯示這頁抗議的畫面,如下:

image

顯示了 60 秒抗議畫面後,就會自動進如原本要連結的頁面。在透過正規的管道而得不到妥善的處置,我也只能用消極的抗意來表達我的不滿。請看到的人留個 MESSAGE 支持一下吧,或是有推推王帳號的人也幫忙推一下,一起對不重視智慧財產權的百度表答不滿 & 抗議!

 

抗議之餘,本站再怎樣也是討論進階 .NET 技術的網站,就拿這次的案例,看看這樣的 HttpModule 該怎麼處理! 未來如果你也不幸碰到這樣的事件 (最好不要碰到),可以拿出來用一用! 要替網站加上這樣的功能很簡單,只要在 Web.config 把你寫的 HttpModule 掛上就好。一旦掛上,所有針對這個網站的 Http Request 都會經過你的 HttpModule 處理,任何一個 LINK 都跑不掉!

 

ASP.NET HttpModule開發範例: 把所有來自百度的使用者,引導到抗議的畫面![copy code]
public class SiteBlockerHttpModule : IHttpModule{    public void Init(HttpApplication context)    {        context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);    }    void context_AuthenticateRequest(object sender, EventArgs e)    {        HttpApplication application = sender as HttpApplication;        string referer = application.Context.Request.ServerVariables["HTTP_REFERER"];        if (string.IsNullOrEmpty(referer) == false)        {            Uri refererURL = new Uri(referer);            if (refererURL.Host.ToUpperInvariant().Contains("BAIDU.COM") == true)            {                application.Context.Server.Transfer("~/Blogs/ShowBlockedMessage.aspx");            }        }    }}
    
   1:  public class SiteBlockerHttpModule : IHttpModule
    
   2:  {
    
   3:      public void Init(HttpApplication context)
    
   4:      {
    
   5:          context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
    
   6:      }
    
   7:   
    
   8:      void context_AuthenticateRequest(object sender, EventArgs e)
    
   9:      {
    
  10:          HttpApplication application = sender as HttpApplication;
    
  11:          string referer = application.Context.Request.ServerVariables["HTTP_REFERER"];
    
  12:   
    
  13:          if (string.IsNullOrEmpty(referer) == false)
    
  14:          {
    
  15:              Uri refererURL = new Uri(referer);
    
  16:              if (refererURL.Host.ToUpperInvariant().Contains("BAIDU.COM") == true)
    
  17:              {
    
  18:                  application.Context.Server.Transfer("~/Blogs/ShowBlockedMessage.aspx");
    
  19:              }
    
  20:          }
    
  21:      }
    
  22:  }
    

 

 

 

 

--

後記: 針對這次事件的記錄:

  1. 2008‎年‎6‎月‎22‎日, ‏‎下午 11:59:16,第一次張貼抗議的回應 
  2. 2008‎年‎6‎月‎23‎日, ‏‎上午 11:44:50,第二次張貼抗議的回應 
  3. 2008‎年‎6‎月‎23‎日, ‏‎下午 04:53:44,第三次張貼抗議的回應 
  4. ‎2008‎年‎6‎月‎23‎日, ‏‎下午 11:32:05,第四次張貼抗議的回應 
  5. ‎2008‎年‎6‎月‎25‎日, ‏‎下午 08:08:14,第五次張貼抗議的回應 
  6. 2008‎年‎6‎月‎26‎日, ‏‎下午 07:26:36,第六次張貼抗議的回應 
  7. ‎2008‎年‎6‎月‎28‎日, ‏‎上午 12:58:54,百度站方的回應
     


評論

2008/6/30 下午 12:10:52

DanLee

百度一向都很垃圾的。用百度的都是低端用户。到纳斯达克圈了钱就NBHH了。

--
問: 7 x 3 = ?

DanLee cn

2008/7/2 下午 04:47:37

chicken

用戶本來就有好有壞, 就算是 GOOGLE 也是一樣.
不過站方放著不管就很離譜了.

--
借問一下, NBHH 是啥意思? 猜不出來..

--
請輸入: "年年行大運"

chicken tw

2008/7/4 上午 02:18:02

DanLee

呵呵,搞IT的人怎么忘了去google上搜这个关键词 “nbhh 什么意思”
虽然我也是搞软件的,但是对于这些搜索网站或者什么门户网站的盈利模式真的还不懂。靠个卖个关键词,排个序就赚钱,而且还很贵,那以后问路都要要钱了。这些网站还往往被风险投资眷顾,真是搞不懂。 “哥们,去前门怎么走啊”“告诉你免费的路线要走三个小时,走一个小时的路线要10块,走2分钟能到的路线要100块,你看着办吧。。。”

--
請輸入: "叭樂雞萬歲"

DanLee cn

2008/7/6 上午 03:23:50

sea

以後寫文章前可在最前頭標明"擅自轉載者是小孬孬喔!"...不然也可以寫"陳水扁萬歲或支持台灣獨立"之類的...Tong


--
問: 3 + 1 = ?

sea tw

2008/7/6 上午 04:20:08

chicken

哈,我開始想把底下的國旗換成綠色的那一面... Tong

--
問: 8 - 7 = ?

chicken tw

新增評論


(將顯示您的Gravatar圖示)

(請輸入: "海娘娘永遠是對的")
  Country flag




 

大家对此有什么看法的话请随时评论,各抒己见
posted @ 2008-07-28 09:48 李炉烽 阅读(280) 评论(1) 编辑