為自訂伺服器控制項實現事件,是一個比較複雜的過程。開發人員不僅需要根據上一篇文章中介紹的方法,實現捕獲回傳事件,而且有時候還需要參與回傳資料處理過程。本文將通過典型應用介紹處理回傳資料的方法。
1. 實現處理回傳資料
在上一篇文章介紹的捕獲回傳事件程序中,往往都不涉及回傳到伺服器的控制項資料。開發人員主要實現IPostBackEventHandler介面就能夠成功捕獲事件,並為之定義事件處理常式。然而,有些伺服器控制項在應用過程中,涉及回傳資料的變化等情況。例如,自訂控制項是一個輸入控制項,當使用者輸入並回傳後,可能會由於回傳資料的變化而引發一些事件。為了處理以上問題,控制項類必須實現IPostBackDataHandler介面。下面列舉了介面聲明代碼。
public interface IPostBackDataHandler{ public bool LoadPostData ( string postDataKey, NameValueCollection postCollection ); public void RaisePostDataChangedEvent ();}
IPostBackDataHandler介面用於在建立需要由用戶端回傳到伺服器的表單資料的伺服器控制項時使用。如上代碼所示,該介面包括兩個方法,LoadPostData和RaisePostDataChangedEvent。
與實現捕獲回傳事件類別似,僅僅在控制項類中實現介面是不完整的。下面總結了為了實現處理回傳資料而必須實現的兩個要點。
第一、必須在控制項呈現中將控制項的name的屬性值設定為UniqueID。這是由於發生回傳後,頁架構將在發送的內容中搜尋與實現IPostBackDataHandler的伺服器控制項的UniqueID匹配的值,然後才能調用LoadPostData方法。
第二、控制項類必須實現IPostBackDataHandler介面,並實現LoadPostData和RaisePostDataChangedEvent方法。LoadPostData方法用來檢查提交給伺服器的資料。該方法包含兩個參數:postDataKey表示用於識別控制項內資料的關索引值,postData是提交資料的集合,其採用Key/Value結構便於使用索引名稱訪問。要訪問集合中的控制項資料,只要採用如下代碼即可:"string nData = postData[postDataKey]; "。在LoadPostData方法中,通過新資料(用戶端發送的資料值)與舊資料(先前提交給用戶端的資料值)進行比較的結果來確定方法傳回值。如果新舊資料相同,則說明資料沒有被修改,方法傳回值為false;如果新舊資料不同,則表明舊資料已經被用戶端修改,方法傳回值true。下面是LoadPostData方法的一個簡單應用。
public virtual bool LoadPostData(string postDataKey,NameValueCollection postData)
{
string presentValue = Text;
//舊資料
string postedValue = postData[postDataKey];//新資料
//檢查新舊資料
if(presentValue.Equals(postedValue) || presentValue == null) {
Text = postedValue;
return true;
}
return false;
}
如果LoadPostData方法返回true,.NET架構將自動調用RaisePostDataChangedEvent方法。該方法用訊號要求伺服器控制項對象通知ASP.NET應用程式該控制項的狀態已更改,控制項開發人員可以在該方法中定義根據資料變化引發的事件。下面是簡單的調用OnTextChanged方法:
public virtual void RaisePostDataChangedEvent()
{
OnTextChanged(EventArgs.Empty);
}
以上是處理回傳資料的實現要點,掌握這些要點對於事件處理具有至關重要的意義。同時,其內容也說明了以下.NET架構處理回傳資料的過程:
(1)首先在發送的內容中搜尋與實現IPostBackDataHandler的伺服器控制項的UniqueID匹配的值。
(2)調用LoadPostData方法,並返回bool值。
(3)如果LoadPostData方法返回true,那麼調用RaisePostDataChangedEvent方法。
(4)執行RaisePostDataChangedEvent方法中定義的OnEvent方法。
2. 典型應用
下面通過一個典型執行個體說明處理回傳資料的核心過程。建立一個自訂文字框控制項WebCustomControl,其文字屬性Text因回傳而更改。控制項在載入回傳資料後引發TextChanged事件。控制項類原始碼如下所示:
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{
[DefaultProperty("Text")]
[ToolboxData("<{0}:WebCustomControl runat=server></{0}:WebCustomControl>")]
public class WebCustomControl : WebControl, IPostBackDataHandler {
// 實現Text屬性
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text {
get {
string s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set {
ViewState["Text"] = value;
}
}
//重寫控制項呈現方法RenderContents
protected override void RenderContents(HtmlTextWriter output) {
output.AddAttribute(HtmlTextWriterAttribute.Type, "text");
output.AddAttribute(HtmlTextWriterAttribute.Value, Text);
output.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
output.RenderBeginTag(HtmlTextWriterTag.Input);
output.RenderEndTag();
}
//定義事件對象EventTextChanged
private static readonly object EventTextChanged = new object();
#region 實現IPostBackDataHandler 成員
bool IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) {
//比較初始資料presentValue和回傳資料postedValue
string postedValue = postCollection[postDataKey];
string presentValue = Text;
if (presentValue == null || postedValue != presentValue) {
Text = postedValue;
return true;
}
return false;
}
void IPostBackDataHandler.RaisePostDataChangedEvent() {
OnTextChanged(EventArgs.Empty);
}
#endregion // 實現事件處理常式OnTextChanged
private void OnTextChanged(EventArgs eventArgs) {
EventHandler textChangedHandler = (EventHandler)Events[EventTextChanged];
if (textChangedHandler != null) {
textChangedHandler(this, eventArgs);
}
}
// 為TextChanged實現事件屬性結構
public event EventHandler TextChanged {
add {
Events.AddHandler(EventTextChanged, value);
}
remove {
Events.RemoveHandler(EventTextChanged, value);
}
}
}
}
以上原始碼實現了一些重要內容。
(1)控制項類必須實現IPostBackDataHandler,由此可使該控制項參與回傳資料處理。
(2)定義屬性Text,其屬性值儲存在ViewState中。當頁面回傳時,包含Text屬性值的ViewState將被提交到伺服器。
(3)重寫RenderContents方法,並在該方法中定義控制項呈現邏輯。
(4)實現IPostBackDataHandler的方法LoadPostData。比較用戶端發送的資料值與先前伺服器提交給用戶端的資料值是否相同。如果資料相同,說明資料沒有被修改,那麼返回false;如果資料不同,則表明資料已經被用戶端修改,則返回true。
(5)實現IPostBackDataHandler的方法RaisePostDataChangedEvent。如果LoadPostData的傳回值為true,則執行該方法,即要求調用OnTextChanged方法。
(6)定義事件屬性結構TextChanged。在Events事件委託列表中,為EventTextChanged事件委派物件定義Add和Remove訪問器。
(7)定義OnTextChanged方法。
下面是應用自訂伺服器控制項的Default.aspx原始碼:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <%@ Register TagPrefix="wcl" Assembly="WebControlLibrary" Namespace="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 demo1_TextChanged(object sender, EventArgs e) { label1.Text = "您在文字框中輸入的是 " + demo1.Text; } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>處理回傳資料</title> </head> <body> <form id="form1" runat="server"> <div> <wcl:WebCustomControl ID="demo1" runat="server" OnTextChanged="demo1_TextChanged" /> <asp:Button ID="button1" runat="server" Text="提交" /> <br /> <asp:Label ID="label1" runat="server" Font-Size="small"> </asp:Label> </div> </form> </body> </html> |
在以上代碼中,定義了一個WebCustomControl控制項,並為該控制項定義TextChanged事件的處理方法demo1_TextChanged。該方法要求修改Label控制項的Text屬性值。效果圖如圖1和圖2所示。
圖1 頁面初始化效果圖 圖2 頁面提交後的效果圖
可能某些讀者會產生誤解,以為上面的執行個體定義了提交按鈕的Click事件的事件處理方法。實際不然。本執行個體並沒有為提交按鈕定義Click事件的處理方法,而是通過處理回傳資料,並定義WebCustomControl控制項的TextChanged事件來完成的。
3、小結
本文針對實現處理回傳資料的實現方法進行了介紹。掌握這些內容將為開發出具有高品質的伺服器控制項打下良好基礎。至此,通過三篇文章的介紹,相信讀者已經掌握了為自訂伺服器控制項實現事件的基本方法。在隨後的內容中,筆者將繼續介紹利用ASP.NET 2.0技術建立伺服器控制項的其他內容。