top
Loading...
ASP.NET2.0服務器控件之處理回傳數據
為自定義服務器控件實現事件,是一個比較復雜的過程。開發人員不僅需要根據上一篇文章中介紹的方法,實現捕獲回傳事件,而且有時候還需要參與回傳數據處理過程。本文將通過典型應用介紹處理回傳數據的方法。

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技術創建服務器控件的其他內容。
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗