电脑爱好者,提供IT资讯信息及各类编程知识文章介绍,欢迎大家来本站学习电脑知识。 最近更新 | 联系我们 RSS订阅本站最新文章
电脑爱好者
站内搜索: 
当前位置:首页>> asp.net综合>>服务器控件是否必须在runat=server的Form内:

服务器控件是否必须在runat=server的Form内

来源:网络 | 2013-4-27 | (有1429人读过)

对这个概念很多人有误解。以为凡是 WebControl 都必须放在 <form runat="server"></form> 里面。 


(为了说明方便,以下仅列出 aspx 文件中 body 里的内容。) 
1, 


<form id="Form1" method="post" runat="server"> 
</form>    
<asp:TextBox ID="txtHello" Runat="server" Text="OK"></asp:TextBox> 

2, 


<form id="Form1" method="post" runat="server"> 
</form>    
<asp:Label ID="lblHello" Runat="server" Text="Hello"></asp:Label> 

3, 


<form id="Form1" method="post" runat="server"> 
</form>    
<asp:Button ID="btnHello" Runat="server" Text="Hello"></asp:Button> 

结果发现了什么? 

Label 可以正常使用。而 TextBox 和 Button 都会出现抛出一个异常。 

因为 Label, Button, TextBox 都继承自 System.Web.UI.WebControls.WebControl 类。下面我们用 Reflector 来分析一下。 
(如果不了解 Reflector 的可用 google 搜索). 

WebControl 类的部分代码: 


// (Attributes 省略) 
public class WebControl : Control, IAttributeAccessor 

    //  

    protected override void Render(HtmlTextWriter writer) 
    { 
          this.RenderBeginTag(writer);  // here 
          this.RenderContents(writer); 
          this.RenderEndTag(writer); 
    } 
      
    public virtual void RenderBeginTag(HtmlTextWriter writer) 
    { 
          this.AddAttributesToRender(writer);  // here 
          HtmlTextWriterTag tag1 = this.TagKey; 
          if (tag1 != HtmlTextWriterTag.Unknown) 
          { 
                writer.RenderBeginTag(tag1); 
          } 
          else 
          { 
                writer.RenderBeginTag(this.TagName); 
          } 
    } 


Button 类的部分代码: 


// (Attributes 省略) 
public class Button : WebControl, IPostBackEventHandler 

    //  

    protected override void AddAttributesToRender(HtmlTextWriter writer) 

          if (this.Page != null) 
          { 
                this.Page.VerifyRenderingInServerForm(this); // here 
          } 
            // . 

          base.AddAttributesToRender(writer); 
    } 

    void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) 
    { 
          if (this.CausesValidation) 
          { 
                this.Page.Validate(); 
          } 
          this.OnClick(new EventArgs()); 
          this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument)); 
    } 


TextBox 类部分代码: 


// (Attributes 省略) 
public class TextBox : WebControl, IPostBackDataHandler 

    protected override void AddAttributesToRender(HtmlTextWriter writer) 
    { 
        int num1; 
        if (this.Page != null) 
        { 
            this.Page.VerifyRenderingInServerForm(this); // here 
        } 
        writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID); 
        TextBoxMode mode1 = this.TextMode; 

        //  
    } 


Label 类部分代码: 


// (Attributes 省略) 
public class Label : WebControl 

    //  


注意其中 // here 标注的地方。这些就是方法调用跳转的地方。 

从以上的跟踪我们可以得到一个结论: 
只有需要处理回发(PostBack) 的控件才必须放在 Form 内。 
这种控件通常要实现 IPostBackEventHandler 或者 IPostBackDataHandler 接口。 

而上面代码里的 Page.VerifyRenderingInServerForm(this) 方法正是我们做的试验里异常的抛出者。这个方法检测当前控件是否在一个 runat="server" 的 form 内部,并且在 Render 调用中。如果不是,则抛出异常。 
我们看到上面的 Label 类中就保留了基类对 AddAttributesToRender 的默认实现,而没有加入对 Page.VerifyRenderingInServerForm(this)  这个检验的调用机制。 

对控件开发者而言,如果你的控件需要处理回发事件或回发数据,则必须实现 IPostBackEventHandler 或 IPostBackDataHandler 接口。并且为了保险起见,应该重写 AddAttributesToRender 虚拟方法的实现,在其中调用 Page.VerifyRenderingInServerForm(this) 这个检验。 
asp.net综合热门文章排行
网站赞助商
购买此位置

 

关于我们 | 网站地图 | 文档一览 | 友情链接| 联系我们

Copyright © 2003-2024 电脑爱好者 版权所有 备案号:鲁ICP备09059398号