看看具体实现:
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));
}
{
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; }
....
}
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);
}
}
{
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);
}
}
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);
}
}
{
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 :)