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


    对这个概念很多人有误解。以为凡是 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) 这个检验。

  • 相关阅读:
    CC.NET+SVN+Msbuild
    react服务端/客户端,同构代码心得
    为什么国人很难出高质量开源
    FKP,一套全栈框架,基于react、webpack、koa1、babel
    嵌入式工程师的发展路线
    浅谈学习单片机的一些职业规划
    关于嵌入式新手面试的一些小技巧
    几点心得送给学习嵌入式的新手
    新手学习嵌入式需要掌握的几点知识点
    从迷茫到转机,一个嵌入式工程师的经历
  • 原文地址:https://www.cnblogs.com/superfeeling/p/2214176.html
Copyright © 2020-2023  润新知