技术开发 频道

ASP.NET入门:认清.NET控件之Button

    【IT168 评论】“做.NET不值钱,没有技术含量,拖拖控件就行了。”———— 这类言语我最讨厌了,一点技术含量都没有,不懂.NET就瞎嚷嚷。不管做什么,做好都不容易,你没做过怎么知道没有技术含量呢? 我们既享受控件带来的快捷,也知其原理,甚至可以自己开发控件,你还能说我们没技术含量?!

  控件是什么? 是.NET Framework对Html里的元素的封装。 他把一个<input type="button"/>变成了 Button类,把<span></span>变成了Label类,把<input type="select">变成了DropDownList。这就是控件,就是这些类。

  提到了Page类,Page的生命周期里有些事件是和处理控件类有关的。

  PreInit

  使用该事件来执行下列操作:

  检查 IsPostBack 属性来确定是不是第一次处理该页。

  创建或重新创建动态控件。

  动态设置主控页。

  动态设置 Theme 属性。

  读取或设置配置文件属性值。

  Render

  这不是事件;在处理的这个阶段,Page 对象会在每个控件上调用此方法。所有 ASP.NET Web 服务器控件都有一个用于写出发送给浏览器的控件标记的 Render 方法。

  如果创建自定义控件,通常要重写此方法以输出控件的标记。不过,如果自定义控件只合并标准的 ASP.NET Web 服务器控件,不合并自定义标记,则不需要重写 Render 方法。

  一个是初始化,一个是显示,其他的还有事件之类的,我们暂且不提。我们可以看出,初始化其实就是实例化desinger.cs里用到的控件。而最终这些控件都需要转换成HTML标签,也就是被Page调用其Render方法。Page自身也是控件所,以Page的Render就是负责生成HTML的。

  控件类都在System.Web.UI.WebControls下,我们可以打开MSDN查看一些常用控件的类和其相关的事件方法。如果有用Refletor的话,可以打开System.Web.dll查看更加详细的源码。你会发现有意思的继承关系,理解MS的设计理念,也更方便我们对控件有个更加清晰的认识。

  Button类。

  当我们在FORM里放置一个Button,该按钮默认为Submit按钮,如果设为UseSubmitBehavior = false,就可以看到客户端会生成该按钮需要的JS代码。

<div class="aspNetHidden">
    
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
    
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
    
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTcxODU4OTc0MWRk6Htqf5QF2exQx/BOtdDx1djNfbW7y3bPbmRizhypOr4=" />
    
</div>

    
<script type="text/javascript">
    
//<![CDATA[
    var theForm
= document.forms['form1'];
    if (!theForm) {
        theForm
= document.form1;
    }
    
function __doPostBack(eventTarget, eventArgument) {
        
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value
= eventTarget;
        theForm.__EVENTARGUMENT.value
= eventArgument;
        theForm.submit();
        }
    }
    
//]]>
    
</script>
    
<input type="submit" name="Button1" value="Button" id="Button1" />
    
<input type="button" name="Button2" value="Button" onclick="javascript:__doPostBack('Button2','')" id="Button2" />

 

  __doPostBack就是出发form的提交,而Button2调用的时候传值了自己的名字,然后__EVENTTARGET的值被设为了Button2,这样在提交的时候,Post的数据里就会告诉服务端是Button2触发的!再看Button1却没有调用__doPostBack,因为他是submit类型,在提交的时候浏览器会把他的名字默认提交过去,同时其他的按钮不会被提交。

  所以,既然服务端知道了是哪个按钮被点过,自然就会调用该按钮实例的OnClick方法。看看Page类里有一个方法。

if (this.IsPostBack)
{
    this.RaisePostBackEvent(this._requestValueCollection);
}

private void RaisePostBackEvent(NameValueCollection postData)
{
    
if (this._registeredControlThatRequireRaiseEvent != null)
     {
         this.RaisePostBackEvent(this._registeredControlThatRequireRaiseEvent,
null);
     }
    
else
     {
        
string str = postData["__EVENTTARGET"];
         bool flag
= !string.IsNullOrEmpty(str);
        
if (flag || (this.AutoPostBackControl != null))
         {
     Control control
= null;
    
if (flag)
     {
         control
= this.FindControl(str);
     }
    
if ((control != null) && (control.PostBackEventHandler != null))
     {
        
string eventArgument = postData["__EVENTARGUMENT"];
         this.RaisePostBackEvent(control.PostBackEventHandler, eventArgument);
     }
         }
        
else
         {
     this.Validate();
         }
     }
}

 

  啊哈!明白没有?在IsPostBack(也就是提交)后,调用了触发所有控件事件的方法。postData["__EVENTTARGET"]明显就是我们刚才的点的按钮名称,然后通过FindControl得到该对象,最后调用RaisePostBackEvent方法出发该对象的事件。再往下看具体流程:

[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void RaisePostBackEvent(IPostBackEventHandler sourceControl,
string eventArgument)
{
  sourceControl.RaisePostBackEvent(eventArgument);
}

 

  也就是说,Button类必须实现IPostBackEventHandler接口(因为Page不知道控件到底是什么,所以要使用接口,这就是接口的用处)。  

0
相关文章