文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>ASP.NET进阶(5):认清控件 之 Button

ASP.NET进阶(5):认清控件 之 Button

时间:2010-10-15  来源:君之兰

__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不知道控件到底是什么,所以要使用接口,这就是接口的用处)。

看看具体实现:     protected virtual void RaisePostBackEvent(string eventArgument)
    {
         base.ValidateEvent(this.UniqueID, eventArgument);
         if (this.CausesValidation)
         {
             this.Page.Validate(this.ValidationGroup);
         }
         this.OnClick(EventArgs.Empty);
         this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
    }

 

首先是验证,然后是执行OnClick,然后执行OnCommand。呵呵,一个OnClick我们终于走完了~ 感觉如何? 头涨了没?
看下Button类,确实继承IPostBackEventHandler接口。     [Designer("System.Web.UI.Design.WebControls.ButtonDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), SupportsEventValidation, ToolboxData("<{0}:Button runat=\"server\" Text=\"Button\"></{0}:Button>"), DefaultEvent("Click"), DefaultProperty("Text"), DataBindingHandler("System.Web.UI.Design.TextDataBindingHandler, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
    public class Button : WebControl, IButtonControl, IPostBackEventHandler
    {
    ....
        [WebCategory("Action"), WebSysDescription("Button_OnClick")]
        public event EventHandler Click;
        protected virtual void OnClick(EventArgs e)

        [WebCategory("Action"), WebSysDescription("Button_OnCommand")]
        public event CommandEventHandler Command;
    
        [WebSysDescription("Button_Text"), WebCategory("Appearance"), Bindable(true), Localizable(true), DefaultValue("")]
        public string Text { get; set; }
    ....
    }

 

并且看到熟悉的Click,Command,Text,而ID,Width,Height则在他的父类中。
看看OnClick是干嘛的?     protected virtual void OnClick(EventArgs e)
    {
        EventHandler handler = (EventHandler) base.Events[EventClick];
        if (handler != null)
        {
         handler(this, e);
        }
    }

 

OnClick的方法是被点击后执行的方法,具体是从Events里找到EventClick类型的委托,其实就是判断Click事件是否被订阅,如果有该类型委托,则表明已经被订阅,便执行该委托实例(也就是我们定义的Click具体方法)。
再来看下是如何订阅的:     [WebCategory("Action"), WebSysDescription("Button_OnClick")]
    public event EventHandler Click
    {
        add
        {
         base.Events.AddHandler(EventClick, value);
        }
        remove
        {
         base.Events.RemoveHandler(EventClick, value);
        }
    }

 

Click事件具有add和remove两个类似属性的get和set的方法,这当然是C#的特定语法,实际编译后的IL里是两个小方法。 Add是订阅,remove是取消订阅。AddHandler就是把具体的方法和委托类型添加到Events里。     public void AddHandler(object key, Delegate value)
    {
         ListEntry entry = this.Find(key);
         if (entry != null)
         {
             entry.handler = Delegate.Combine(entry.handler, value);
         }
         else
         {
             this.head = new ListEntry(key, value, this.head);
         }
    }

 

一气呵成,我们知道了Click的具体调用实现,且明白的事件的订阅。后面再说控件的其他属性,休息休息。后面会介绍Render和DataBind :) 
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载