ASP.NET2.0伺服器控制項之捕獲回傳事件
來源:互聯網
上載者:User
asp.net|伺服器|控制項 1. 實現捕獲回傳事件
如果伺服器控制項需要捕獲來自用戶端的回傳事件,並想為該回傳事件自訂伺服器端事件處理邏輯,那麼控制項必須實現System.Web.UI.IPostBackEventHandler介面。下面列舉了該介面定義。
public interface IPostBackEventHandler
{
void RaisePostBackEvent(string eventArgument);
}
如上代碼所示,IPostBackEventHandler介面僅包括一個成員方法RaisePostBackEvent。該方法使伺服器控制項能夠處理將表單發送到伺服器時引發的事件,其參數eventArgument表示要傳遞到事件處理常式的可選事件參數。開發人員可以在RaisePostBackEvent方法中實現伺服器控制項回傳過程中執行的邏輯。一般情況下,RaisePostBackEvent方法將引發一個或者多個伺服器端事件。以下程式碼片段顯示了在伺服器上引發Click事件的RaisePostBackEvent實現。
public void RaisePostBackEvent(String eventArgument)
{
OnClick(EventArgs.Empty);
}
實現捕獲回傳事件並不是僅僅使伺服器控制項類實現IPostBackEventHandler介面,並實現該介面成員方法就可以的。開發人員還需要注意實現其他內容。下面列舉了實現捕獲回傳事件程序中的三個要點。
第一,也是最重要的,即自訂伺服器控制項類必須實現IPostBackEventHandler介面,並實現該介面成員RaisePostBackEvent方法。這一過程在上文中已經進行了介紹。
第二,為控制項分配UniqueID。
定義引起回傳事件的控制項的name屬性值為UniqueID,是正確實現RaisePostBackEvent方法的關鍵之一。當引發回傳後,頁架構就會搜尋發送的內容,並確定發送對象的名稱是否與實現IPostBackEventHandler的伺服器控制項的UniqueID對應。如果對應,頁架構就會在該控制項上調用RaisePostBackEvent方法。這裡的重點是需要開發人員在呈現邏輯中,為控制項的name屬性分配UniqueID。下面列舉了一個簡單的程式碼範例。
protected override void Render(HtmlTextWriter output)
{
output.Write("<INPUT TYPE=submit name="+this.UniqueID+"Value='Click Me' />");
}
如上代碼所示,在控制項呈現方法Render中,呈現了一個按鈕,其name屬性值為UniqueID。只有為引起回傳的控制項的name屬性分配了UniqueID,才能夠正確實現捕獲回傳事件。
第三,實現事件屬性結構。
事件屬性結構是一種最佳化的事件實現方式。在介紹之前,我們首先看看常見的控制項事件實現方式。具體代碼如下所示。
......
public class WebCustomControl:WebControl,IPostBackEventHandler{
//聲明Click事件委託
public event EventHandler Click;
//實現RaisePostBackEvent方法
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
OnClick(EventArgs.Empty);
}
//定義OnClick事件處理常式
protected virtual void OnClick(EventArgs e) {
if(Click != null) { Click(this,e); }
}
......
}
在以上代碼中,包括了與事件定義相關的三個關鍵內容:一、定義Click事件委託;二、控制項類實現了IPostBackEventHandler介面,其中當實現介面成員方法RaisePostBackEvent過程中,定義了事件處理常式OnClick;三、實現OnClick事件處理常式。以上實現方法簡單易用,然而卻存在一個缺點,即執行效率低。尤其是在一個類中引發多個事件的情況下,將會增加開銷,浪費大量伺服器資源,最終導致運行效率降低。
為瞭解決以上問題,下面介紹一種最佳化的事件實現方式--事件屬性結構。該結構使用System.ComponentModel.EventHandlerList類,這個類提供一個簡單的委託列表。通過使用該類所提供的相關方法,開發人員能夠靈活的操作控制項的事件處理常式委託列表。例如,控制項中的Click事件,使用事件屬性結構如下:
protected static readonly object EventClick = new object();
public event EventHandler Click{
add {
Events.AddHandler(EventClick,value);
}
remove {
Events.RemoveHandler(EventClick,value);
}
}
在事件屬性結構定義之前,首先需要定義Click事件委派物件。由於每個事件僅建立一次,因此,需要聲明為靜態和唯讀。然後,在屬性結構中通過AddHandler、RemoveHandler方法操作事件處理常式委託列表。當頁面調用Click事件時,它向控制項的EventHandlerList集合中添加或者刪除處理常式。由於這種實現方法,在多個事件的聲明過程中比普通的實現方法效率高,因此是非常值得推薦的方法。
另外,在OnClick方法的實現過程中,當用一個事件屬性時,必須從EventHandlerList中取回委託,並將其轉換成EventHandler的類型。
protected virtual void OnClick(EventArgs e){
EventHandler clickHandler = (EventHandler)Events[EventClick];
if(clickHandler != null) {
clickHandler(this,e);
}
}
請讀者注意:事件屬性結構不適用於VB.net語言,只能在C#等語言中應用。
2. 典型應用
實事求是的講,以上捕獲回傳事件的理論介紹對於從未實現過伺服器控制項事件的讀者而言,有些難以理解。為此,本小節通過一個典型的樣本來具體說明捕獲回傳事件的實現方法。
本例實現了一個自訂伺服器控制項WebCustomControl。該控制項雖然呈現為一個按鈕外觀,但是其並不是從Button類繼承而來。當單擊該按鈕時,控制項將引起回傳,伺服器端自動捕獲回傳的單擊事件,並且引發Click事件,執行對應事件處理常式。下面是伺服器控制項實現的原始碼代碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebControlLibrary{ [DefaultEvent("Click")]
[ToolboxData("<{0}:WebCustomControl runat=server></{0}:WebCustomControl>")]
public class WebCustomControl : WebControl, IPostBackEventHandler {
// 定義一個Click事件委派物件
private static readonly object EventClick = new object();
//實現Click事件屬性
[Description("Click事件屬性"), Category("Action") ]
public event EventHandler Click {
add {
Events.AddHandler(EventClick, value);
}
remove {
Events.RemoveHandler(EventClick, value);
}
}
// 重寫控制項呈現方法RenderContents
protected override void RenderContents(HtmlTextWriter output) {
output.Write("<input type='submit' name=" + this.UniqueID + " value=請單擊 />");
}
//實現事件方法
protected virtual void OnClick(EventArgs e) {
EventHandler clickHandler = (EventHandler)Events[EventClick];
if (clickHandler != null) {
clickHandler(this, e);
}
}
// 實現IPostBackEventHandler介面成員
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
OnClick(EventArgs.Empty);
}
}
}
在WebCustomControl類中,實現了以下有關捕獲回傳事件處理的關鍵內容:
·控制項類WebCustomControl實現IPostBackEventHandler;
·將引發回傳的控制項的name屬性值設定UniqueID;
な迪質錄糶越峁梗な錄遝絛蛭辛斜恚?BR>
·在RaisePostBackEvent方法中調用OnClick方法;
下面的代碼是應用自訂按鈕WebCustomControl的Default.ASPx原始碼,顯示效果如圖1和圖2所示。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ ReGISter TagPrefix="cc" Namespace="WebControlLibrary" Assembly="WebControlLibrary" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void wcc1_Click(object sender, EventArgs e) {
message.Text = "您剛才點擊了上面的按鈕";
}
</script>
<html XMLns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>捕獲回傳事件</title>
</head>
<body>
<form id="form1" runat="server">
<center>
<cc:WebCustomControl ID="wcc1" runat="server" /> <br /> <br />
<asp:Label ID="message" runat="server"></asp:Label>
</center>
</form>
</body>
</html>
下圖1和圖2是應用效果圖。
圖 1 頁面初始化效果圖 圖2 點擊按鈕後的效果圖
另外,還有一個與捕獲回傳事件密切相關的屬性AutoPostBack。該屬性用於控制項的自動回傳設定,很多標準的伺服器控制項中均包含該屬性。對於開發人員來講,是否需要在自行建立的伺服器控制項中定義該屬性是很重要的,需要根據控制項的功能需求認真考慮取捨。該屬性的關鍵代碼實現如下:
//定義屬性AutoPostBack
public bool AutoPostBack{
set {
this._autoPostBack = value;
}
get {
return this._autoPostBack;
}
}
//在Render方法中添加Page.GetPostBackEventReference()方法
protected override void Render(HtmlTextWriter output){
......
if(this.AutoPostBack) {
writer.WriteAttribute("ontextchanged","JavaScript:" + Page.GetPostBackEventReference(this));
}
......
}
由以上代碼可知,AutoPostBack屬性的實現重點是Page.GetPostBackEventReference方法的應用。該方法擷取對用戶端指令碼函數的引用,調用該函數將使伺服器發送回該頁,並返回一段表示用戶端事件的字串,實際是一些用戶端代碼。當AutoPostBack="true"時,伺服器控制項將發生自動回傳,而不需通過Click事件等引發;當AutoPostBack="false",則回傳必須經過類似Click的事件引發。
以上介紹的是有關捕獲回傳事件的具體實現方法。總體來講不是非常複雜,然而,實現捕獲回傳事件的具體應用非常靈活,遠遠沒有這麼簡單,這就需要讀者不斷的實踐才能深入理解。
3. 小結
本文首先介紹了利用ASP.NET 2.0技術,為自訂伺服器控制項實現捕獲回傳事件的實現方法。通過這些內容,相信讀者可以基本掌握實現控制項捕獲回傳事件的方法。在隨後的文章中,筆者將繼續介紹實現事件處理的另一核心內容--處理回傳資料。