1. 實(shí)現(xiàn)處理回傳數(shù)據(jù)
在上一篇文章介紹的捕獲回傳事件過程中,往往都不涉及回傳到服務(wù)器的控件數(shù)據(jù)。開發(fā)人員主要實(shí)現(xiàn)IPostBackEventHandler接口就能夠成功捕獲事件,并為之定義事件處理程序。然而,有些服務(wù)器控件在應(yīng)用過程中,涉及回傳數(shù)據(jù)的變化等情況。例如,自定義控件是一個(gè)輸入控件,當(dāng)用戶輸入并回傳后,可能會(huì)由于回傳數(shù)據(jù)的變化而引發(fā)一些事件。為了處理以上問題,控件類必須實(shí)現(xiàn)IPostBackDataHandler接口。下面列舉了接口聲明代碼。
public interface IPostBackDataHandler{ public bool LoadPostData ( string postDataKey, NameValueCollection postCollection ); public void RaisePostDataChangedEvent ();} |
IPostBackDataHandler接口用于在創(chuàng)建需要由客戶端回傳到服務(wù)器的窗體數(shù)據(jù)的服務(wù)器控件時(shí)使用。如上代碼所示,該接口包括兩個(gè)方法,LoadPostData和RaisePostDataChangedEvent。
與實(shí)現(xiàn)捕獲回傳事件類似,僅僅在控件類中實(shí)現(xiàn)接口是不完整的。下面總結(jié)了為了實(shí)現(xiàn)處理回傳數(shù)據(jù)而必須實(shí)現(xiàn)的兩個(gè)要點(diǎn)。
第一、必須在控件呈現(xiàn)中將控件的name的屬性值設(shè)置為UniqueID。這是由于發(fā)生回傳后,頁框架將在發(fā)送的內(nèi)容中搜索與實(shí)現(xiàn)IPostBackDataHandler的服務(wù)器控件的UniqueID匹配的值,然后才能調(diào)用LoadPostData方法。
第二、控件類必須實(shí)現(xiàn)IPostBackDataHandler接口,并實(shí)現(xiàn)LoadPostData和RaisePostDataChangedEvent方法。LoadPostData方法用來檢查提交給服務(wù)器的數(shù)據(jù)。該方法包含兩個(gè)參數(shù):postDataKey表示用于識別控件內(nèi)數(shù)據(jù)的關(guān)鍵值,postData是提交數(shù)據(jù)的集合,其采用Key/Value結(jié)構(gòu)便于使用索引名稱訪問。要訪問集合中的控件數(shù)據(jù),只要采用如下代碼即可:"string nData = postData[postDataKey]; "。在LoadPostData方法中,通過新數(shù)據(jù)(客戶端發(fā)送的數(shù)據(jù)值)與舊數(shù)據(jù)(先前提交給客戶端的數(shù)據(jù)值)進(jìn)行比較的結(jié)果來確定方法返回值。如果新舊數(shù)據(jù)相同,則說明數(shù)據(jù)沒有被修改,方法返回值為false;如果新舊數(shù)據(jù)不同,則表明舊數(shù)據(jù)已經(jīng)被客戶端修改,方法返回值true。下面是LoadPostData方法的一個(gè)簡單應(yīng)用。
public virtual bool LoadPostData(string postDataKey,NameValueCollection postData) { string presentValue = Text; //舊數(shù)據(jù) string postedValue = postData[postDataKey];//新數(shù)據(jù) //檢查新舊數(shù)據(jù) if(presentValue.Equals(postedValue) || presentValue == null) { Text = postedValue; return true; } return false; } |
如果LoadPostData方法返回true,.NET框架將自動(dòng)調(diào)用RaisePostDataChangedEvent方法。該方法用信號要求服務(wù)器控件對象通知ASP.NET應(yīng)用程序該控件的狀態(tài)已更改,控件開發(fā)者可以在該方法中定義根據(jù)數(shù)據(jù)變化引發(fā)的事件。下面是簡單的調(diào)用OnTextChanged方法:
public virtual void RaisePostDataChangedEvent() { OnTextChanged(EventArgs.Empty); } |
以上是處理回傳數(shù)據(jù)的實(shí)現(xiàn)要點(diǎn),掌握這些要點(diǎn)對于事件處理具有至關(guān)重要的意義。同時(shí),其內(nèi)容也說明了以下.NET框架處理回傳數(shù)據(jù)的過程:
。1)首先在發(fā)送的內(nèi)容中搜索與實(shí)現(xiàn)IPostBackDataHandler的服務(wù)器控件的UniqueID匹配的值。
。2)調(diào)用LoadPostData方法,并返回bool值。
。3)如果LoadPostData方法返回true,那么調(diào)用RaisePostDataChangedEvent方法。
。4)執(zhí)行RaisePostDataChangedEvent方法中定義的OnEvent方法。
2. 典型應(yīng)用
下面通過一個(gè)典型實(shí)例說明處理回傳數(shù)據(jù)的核心過程。創(chuàng)建一個(gè)自定義文本框控件WebCustomControl,其文本屬性Text因回傳而更改。控件在加載回傳數(shù)據(jù)后引發(fā)TextChanged事件?丶愒创a如下所示:
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 { // 實(shí)現(xiàn)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; } } //重寫控件呈現(xiàn)方法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 實(shí)現(xiàn)IPostBackDataHandler 成員 bool IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { //比較初始數(shù)據(jù)presentValue和回傳數(shù)據(jù)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 // 實(shí)現(xiàn)事件處理程序OnTextChanged private void OnTextChanged(EventArgs eventArgs) { EventHandler textChangedHandler = (EventHandler)Events[EventTextChanged]; if (textChangedHandler != null) { textChangedHandler(this, eventArgs); } } // 為TextChanged實(shí)現(xiàn)事件屬性結(jié)構(gòu) public event EventHandler TextChanged { add { Events.AddHandler(EventTextChanged, value); } remove { Events.RemoveHandler(EventTextChanged, value); } } } } |
以上源代碼實(shí)現(xiàn)了一些重要內(nèi)容。
。1)控件類必須實(shí)現(xiàn)IPostBackDataHandler,由此可使該控件參與回傳數(shù)據(jù)處理。
。2)定義屬性Text,其屬性值保存在ViewState中。當(dāng)頁面回傳時(shí),包含Text屬性值的ViewState將被提交到服務(wù)器。
。3)重寫RenderContents方法,并在該方法中定義控件呈現(xiàn)邏輯。
。4)實(shí)現(xiàn)IPostBackDataHandler的方法LoadPostData。比較客戶端發(fā)送的數(shù)據(jù)值與先前服務(wù)器提交給客戶端的數(shù)據(jù)值是否相同。如果數(shù)據(jù)相同,說明數(shù)據(jù)沒有被修改,那么返回false;如果數(shù)據(jù)不同,則表明數(shù)據(jù)已經(jīng)被客戶端修改,則返回true。
。5)實(shí)現(xiàn)IPostBackDataHandler的方法RaisePostDataChangedEvent。如果LoadPostData的返回值為true,則執(zhí)行該方法,即要求調(diào)用OnTextChanged方法。
。6)定義事件屬性結(jié)構(gòu)TextChanged。在Events事件委托列表中,為EventTextChanged事件委托對象定義Add和Remove訪問器。
。7)定義OnTextChanged方法。
下面是應(yīng)用自定義服務(wù)器控件的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>處理回傳數(shù)據(jù)</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> |
在以上代碼中,定義了一個(gè)WebCustomControl控件,并為該控件定義TextChanged事件的處理方法demo1_TextChanged。該方法要求修改Label控件的Text屬性值。效果圖如圖1和圖2所示。
圖1 頁面初始化效果圖 圖2 頁面提交后的效果圖 |
可能某些讀者會(huì)產(chǎn)生誤解,以為上面的實(shí)例定義了提交按鈕的Click事件的事件處理方法。實(shí)際不然。本實(shí)例并沒有為提交按鈕定義Click事件的處理方法,而是通過處理回傳數(shù)據(jù),并定義WebCustomControl控件的TextChanged事件來完成的。
3、小結(jié)
本文針對實(shí)現(xiàn)處理回傳數(shù)據(jù)的實(shí)現(xiàn)方法進(jìn)行了介紹。掌握這些內(nèi)容將為開發(fā)出具有高質(zhì)量的服務(wù)器控件打下良好基礎(chǔ)。至此,通過三篇文章的介紹,相信讀者已經(jīng)掌握了為自定義服務(wù)器控件實(shí)現(xiàn)事件的基本方法。在隨后的內(nèi)容中,筆者將繼續(xù)介紹利用ASP.NET 2.0技術(shù)創(chuàng)建服務(wù)器控件的其他內(nèi)容.