[ASP.NET入門隨想十一] 信客—— 事件架構

來源:互聯網
上載者:User
[ASP.NET入門隨想十一] 信客
——
事件架構
 

   
記得早年在鄉間,對外的通訊往來主要依靠一種特殊職業的人:信客。外出謀生的人多了,少不了要帶幾封平安家信、捎一點衣物食品的,那就用得著信客了。信客
要有一點文化,知道各大碼頭的情形,還要一副強健的筋骨,背得動重重的行李。信客沉重的腳步,是鄉村和城市的紐帶。

——
餘秋雨《文化苦旅•信客》

 

一個饅頭引發的血案 –
回傳與事件

   
基於WEB的分布式系統中,使用者往往是通過提交表單,瀏覽器產生相應的HTTP
POST請求來提出互動申請,這個過程稱為回傳(PostBack)。在同一個網頁中,常會有許多HTML標籤可
能引起回傳,申請交於伺服器處理。
 


   
控制項對應著用戶端的HTML標籤,有著自己的狀態和行為。使用者操作引起每一次回傳,會調用頁面中一個或多個控制項行為修改其狀態,也就是說,杯中的粉圓
(《隨
想十》中對控制項的比喻)之間是有關聯的,使用者撥動其中一個,可能引起其它粉圓震動。拓展開來,當使用者操作或系統內部引髮狀態改變時,
類需要發送一個訊息給關聯類別,讓關聯類別做相應的狀態調整。在.NET架構中,這個訊息被稱為事件(event),
發接訊息的類被稱為事件來源(event
source),關聯類別被稱為事件接收者(event
sink)。回傳的處理過程,實質上是事件來源呼叫事件接收者的行為函數,稱為回調(callback)。

   
我們不希望在編譯時間就確定回調的對象,否則這種強耦合關係就意味著每次使用時需要拎一串關聯粉圓放到杯子中。相反,我們希望到運行時再來確定回調關係,
在.NET架構中,這種方式被定義成委託(delegate),我們在《隨
想七》和《隨想八
》已經對其有了初步的認識。事件基於發布-訂閱機制,每一個產生事件的類都有一個委託成員(發布機制),在系統初始化時,接收器或其
它類需要將具體的事件處理常式綁定到委託成員(訂閱機制),運行時,系統自動完成回調。


口信
–使用者操作引發的伺服器端事件

    “終於有婦女來給信客說悄悄話:‘關照他,往後帶東西幾次並一次,不要雞零狗碎的’;‘你給他說說,那些貨色不能在上海存存?我一個女人家,來強盜來賊怎
麽辦’……信客沉穩地點點頭。”

    使用者會對用戶端瀏覽器中的頁面元素做出各種操作,瀏覽器可以通過JavaScript之類的指令碼語言來捕獲這些操作並且做出相應回應,但對伺服器而言,它
卻常常視而不見。要產生伺服器端事件,就必須在設計期讓事件來源對應的表單元素引髮帶有鮮明特徵的回傳,從而讓頁面能夠正確識別,並傳遞給控制項以做相應回
調,完成使用者操作到事件的映射過程。

   
ASP.NET用介面
IPostBackEventHandler做為信客的口信,帶回遠方的訊息,它包含一個方法:
RaisePostBackEvent。在回傳後,頁面會在控制項樹中尋找與引發回傳HTML元素的UniqueID相匹配的控制項,並
調用該方法,下例為依賴於使用者點擊引發事件的自訂控制項範例。

// MyControls.cs 自訂控制項集<
/font>
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace essay

   
public class myButton:WebControl,IPostBackEventHandler
   
{
   
   
//定義控制項屬性Text
   
    public virtual string Text    
   
   
{
       
   
get 
       
   
{
           
   
string s =(string)ViewState["Text"];
           
   
return (s==null)?string.Empty:s;
       
   
}
       
    set {ViewState["Text"]=value;}
   
   
}
   
    //產生控制項對應的HTML代碼
   
    protected override void Render(HtmlTextWriter writer) 
   
   
{
writer.Write("<INPUT TYPE=submit name=" + this.UniqueID + " Value='"+this.Text+"' />"); 
   
   
}  
   
   
//定義Click事件委託
   
   
public event EventHandler Click;
   
   
//把用戶端提交映射到自訂的Click事件

   
   
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
   
   
{    OnClick(EventArgs.Empty);    }
   
   
//實現回調
   
    protected virtual void OnClick(EventArgs e)
   
   
{    if(Click!=null)Click(this,e);    }
   
}
}

■ 行李 –
回傳資料引發的伺服器端事件

    一次,村裡一戶人家的姑娘要出嫁,姑娘的父親在上海謀生,托老信客帶來兩匹紅綢。”

   
除了依賴於使用者操作引發事件外,我們時常還需要根據回傳的使用者資料,來修改相應控制項的狀態,從而引發事件。

   
回傳的用戶端表單資料會被集中整理到包含資料名/值集的一個
System.Collections.Specialized.NameValueCollection執行個體中,頁面會利用UniqueID在控制項樹中
尋找匹配控制項,如果匹配控制項實現介面
IpostBackDataHandler,則調用
LoadPostData方法更新狀態並返回更新標識,
RaisePostDataChangedEvent方法檢查標識從而引發事件。下例為依賴於狀態變化引發事件的自訂控制項範例。拓
展一下,可以更加靈活地使用這個事件機制,例如當使用者輸入特定資料時,也可以在此引發特定事件。
 &
nbsp; 

using System;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;

namespace essay {
   
public class MyTextBox: Control, IPostBackDataHandler 
   
{
         //定義控制項屬性Text
   
    public String Text 
   
   
{
   
       
get {return (String) ViewState["Text"];}
       
   
set {ViewState["Text"] = value;}                  
   
   
}            
   
    //產生控制項對應的HTML代碼
   
   
protected override void Render(HtmlTextWriter output) 
   
   
{
writer.Write("<INPUT TYPE=text name=" + this.UniqueID + " Value='"+this.Text+"' />"); 
   
   
}
   
    //定義TextChanged事件委託<
span style="color:
#008000;">
   
    public event EventHandler TextChanged;
   
    //更新控制項的Text狀態並返回更新標識
<
/span>   
    //參數NameValueCollection為回傳資料集<
/span>
   
    public virtual bool LoadPostData(string postDataKey, 
                  NameValueCollection values) 
   
   
{
   
       
string presentValue = Text;
           
string postedValue = values[postDataKey];
           
if (!presentValue.Equals(postedValue))
   
       
{
      
        
Text = postedValue;
               
return true;
           
}
           
return false;
   
   
}    
   
    //檢查更新標識引發自訂事件TextChanged<
/span>
       
public virtual void RaisePostDataChangedEvent() 
   
   
{OnTextChanged(EventArgs.Empty);}
   
    //實現回調
       
protected virtual void OnTextChanged(EventArgs e)
   
    {if (TextChanged != null)TextChanged(this,e);}         
   
}
}    


■ 眼神 –
非回傳事件與完整的控制項執行生命週期

    “只要信客一回村,他家裡總是人頭濟濟。多數都不是來收發信、物的,只是來看個熱鬧。農民的眼光裡,有羨慕,有嫉妒;比較得多了,也有輕蔑,有嘲笑。這些
眼神,是千年故土對城市的探詢。”

    以上兩個事件機制皆與回傳有直接關係,利用.NET的事件架構,我們可以在控制項中的任何一個地方引發非回傳事件。例如我們可以在頁面中加入對使用者透明的用
戶行為分析處理控制項,窺視其它控制項狀態從而引發其特定的事件。

  
 
至此,我們已經深入瞭解與控制項執行相關的各種要素細節,最後,通過圖11-2,我們小結一下控制項完整的執行生命週期。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.