asp.net|web|建立|控制項 從使用基本的文字編輯器到創作標記頁面,Web 開發已經經曆了一個漫長的過程。目前,整合式開發環境 (IDE) 為開發過程中的幾乎每個方面都提供了圖形化表示形式。此外,還實現各種說明性編程技術以提高效率並降低出現錯誤的幾率。Visual Studio 2005 和 ASP.NET 2.0 中的控制項體繫結構遵循了這些編程趨勢,並且提供了可靠的、可擴充的環境,該環境設計為使開發人員可以建立能夠以說明方式配置的控制項。
此外,ASP.NET 中新的自適應呈現模型減少了編寫可專門識別其目標瀏覽器的控制項的需要。換句話說,控制項開發人員可以專註於設計控制項,而讓 ASP.NET 架構負責轉換控制項並針對不同類型的瀏覽器和裝置呈現它。
儘管 ASP.NET 2.0 在控制項設計過程中提供了增量改進功能,但實際控制項呈現模型已經完全進行了更改。作為自訂控制項開發人員,您將會看到利用 ASP.NET 的幾個新選項。最重要的是,您將會發現只需編寫較少的代碼便可完成相同的任務。
在 ASP.NET 2.0 中,建立自訂伺服器控制項有很多方法,每種方法都有其優點和局限性。本文將討論與自訂控制項的建立和配置相關的詳細資料。程式碼範例和體繫結構概念要求您對 C# 程式設計語言具有中等水平的理解。
自適應呈現模型
在 ASP.NET 1.x 中,自訂控制項開發人員必須設計每個伺服器控制項,以便它可以識別不同的瀏覽器類型並發出正確的輸出。ASP.NET 1.x 控制項架構提供了幾項功能以使該任務變得更簡單,但開發人員仍然必鬚根據瀏覽器的類型編寫切換程式、開發適當的 HTML,然後針對不同類型的瀏覽器測試控制項。此外,如果開發人員希望控制項在行動裝置上顯示,他必須建立一個與普通 網頁瀏覽器上使用的控制項不同的全新控制項。
ASP.NET 2.0 通過新的自適應呈現模型簡化了瀏覽器檢測和呈現過程。在 ASP.NET 2.0 中引入的自適應呈現模型旨在用於支援那些眾多能夠使用標記格式(包括 HTML、WML、XHTML 或 CHMTL)的不同裝置。
自適應呈現模型體繫結構
每個控制項都可以連結到一個適配器,它會針對特定的目標裝置修改控制項的行為和標記。例如,HTML 適配器將 ASP.NET 控制項產生為標準的 HTML 和 DHTML,以便普通 網頁瀏覽器使用。另一方面,WML 適配器將相同的控制項轉換成無線傳輸標記語言,以便蜂窩電話或其他行動裝置使用。
圖 1. 控制項-適配器壽命周期
上圖說明了控制項方法與適配器方法之間一對一的映射。如果有適配器(如果控制項的 Adapter 屬性不為空白),執行就會在控制項和適配器方法之間傳輸,如上圖所示。在產生階段,控制項對象或配接器物件都可以產生輸出(通常情況下兩者不同時產生輸出)。通常情況下,如果有適配器,那麼適配器的實現將覆蓋控制項的實現。在 ASP.NET 2.0 中,自適應呈現模型適用於所有 ASP.NET 控制項(不僅僅是行動控制項),並且允許 ASP.NET 2.0 支援統一的控制項體繫結構。
實際意義
自適應呈現模型的實際意義有兩個主要方面。第一,作為開發人員,您可以設計一次控制項並期望它可以在具有適配器的任何類型的裝置或瀏覽器上使用。第二,您可以對常用適配器利用廣泛的 Microsoft 測試,減少您自己瀏覽器的特定測試。
自適應呈現模型還為 ASP.NET 2.0 提供了將其他服務添加到控制項產生過程中的機會。由於具有適配器模型,您可以:
1) 根據目標的類型,使用篩選器 來更改控制項的外觀。
2) 根據目標的類型,使用模板來更改整個頁面配置。
3) 根據瀏覽器控制在瀏覽器上的呈現,而不必依賴於 ASP.NET 1.x 的 uplevel/downlevel 確定。
在本文中,我們將重點放在建立自訂控制項的應用方面。但是,請牢記自適應呈現模型是新的基礎架構。
建立自訂伺服器控制項
Visual Studio 2005 提供了很多用於開發自訂伺服器控制項的有用工具。為了說明某些功能,我們將建立一個 MailLink 控制項,它公開了兩個屬性:Email 和 Text。該控制項將產生必需的 HTML 來將所提供的 Text 封裝到 mailto: 連結標記中。
建立項目
在 Visual Studio 2005 中,我們通過在建立項目嚮導中選擇適當的表徵圖來建立一個新的“Web Control Library”項目:
圖 2. Visual Studio 2005 中的建立項目嚮導
該項目是利用預設的自訂控制項類實現建立的。對於我們的樣本,我們將該預設檔案重新命名為 MailLink.cs。
接下來,我們需要添加 Text 屬性。Text 屬性與 Email 屬性稍有不同,因為我們希望將 Text 顯示為由 MailLink 控制項發出的 HTML 的一部分。為此,我們需要從 System.Web.UI 命名空間中添加一個新的特性。
[Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text to display on the link."),
Localizable(true),
PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public virtual string Text {
get {
string s = (string)ViewState["Text"];
return (s == null) ? String.Empty : s;
}
Set {
ViewState["Text"] = value;
}
}
Text 屬性的 PersistenceMode(PersistenceMode.InnerDefaultProperty) 特性(粗體代碼)指定設計器應該將該屬性作為控制項標記內的內部內容序列化。該特性還聲明 Text 是控制項的預設屬性。當使用者在 Visual Studio 中使用這個控制項時,Text 屬性將會作為該控制項的內部文本自動顯示在圖形設計器上,並且如果使用者單擊該控制項並嘗試更改顯示的文本,Text 屬性將會自動更改。
另一方面,應用到屬性的特性會影響設計期間使用者與控制項的互動方式。在運行過程中,這些特性被 ASP.NET 運行時忽略。
有關 ViewState 的注釋
請注意,用於兩個屬性的 Get 和 Set 方法都利用 ViewState 對象。ViewState 對象是一個內建到 WebControl 類中的協助器對象。從開發角度講,ViewState 可被視為一個集合類,用於儲存在回傳過程中我們想要保留的任意屬性。實際上,ViewState 封裝了確定如何執行持久性(使用 Cookie、會話等等)所需的所有代碼和邏輯。
產生控制項
在定義了控制項屬性之後,接下來的步驟就是要設計將由控制項發出的實際響應。在 MailLink 樣本中,我們希望設計控制項來產生基本的 HTML 標籤。
[Bindable(true), Category("Appearance"),
DefaultValue("Please enter your date of birth:"),
Description("Text to prompt user with.")
Localizable(true)]
public virtual String Prompt {
get
{
string s = (string)ViewState["Prompt"];
return (s == null) ? String.Empty : s;
}
set {
ViewState["Prompt"] = value;
}
}
再一次,我們使用特性為屬性提供說明和預設值。我們選擇了使提示可以進行本地化,以便該控制項無論何時都可以用於要求進行國際化的應用程式中。實際的提示可以綁定到包含語言特定文本的資源檔。
在 Web Form頁面中,與伺服器控制項關聯的事件由用戶端引發並由 Web 服務器處理。對於在客戶機上由伺服器控制項引發的事件,ASP.NET 2.0 事件模型收集有關請求的資訊,並使用 HTTP Post 將詳細資料傳遞到伺服器。伺服器上的 Page Framework 對該公告作出解釋以確定發生的事件,然後調用適當的處理常式方法。
圖 8. 典型的伺服器控制項事件
ASP.NET 2.0 可處理幾乎所有捕獲、傳輸和解釋事件的方法。詳細資料對於開發人員來說是隱藏的,開發人員只需要關心伺服器上的處理常式方法的實現。
以下 Web 頁使用回調機制查詢服務器以獲得其目前時間。該頁面彈出一個 JavaScript 警告,在無需完整頁面回傳的情況下顯示目前時間。
<%@ Page Language="C#" CompileWith="Default3.aspx.cs" ClassName="Default3_aspx" %>
<%@ Register TagPrefix="cc1" Namespace="MyControls" Assembly="WebControlLibrary3" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<script language="javascript">
function GetServerTime() {
var message = '';
var context = '';
<%=CallBack%>
}
function ShowServerTime(timeMessage, context) {
alert('The time on the server is:\n' + timeMessage);
}
function OnError(message, context) {
alert('An unhandled exception has occurred:\n' + message);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<cc1:timesnap id="TimeSnap1" runat="server"> </cc1:timesnap>
<input type="button" value="GetTime" />
</div>
</form>
</body>
</html>
上述頁面原始碼包含三個關鍵 JavaScript 函數:GetServerTime()、ShowServerTime() 和 OnError()。這些 JavaScript 函數與頁面的 GetCallbackEventReference 帶外請求相關聯。
public partial class Default3_aspx {
public string CallBack;
void Page_Load(object sender, EventArgs e) {
CallBack = this.GetCallbackEventReference(TimeSnap1,"message","ShowServerTime","context","OnError");
}
}
GetCallbackEventReference 方法需要為其第一個參數實現 ICallbackEventHandler 介面的對象。通過實現 RaiseCallbackEvent() 方法,TimeSnap 自訂伺服器控制項符合介面要求。
public class TimeSnap : WebControl, ICallbackEventHandler
{
...
public string RaiseCallbackEvent(string eventArgument) {
// Uncomment next line to test error handler
// throw new ApplicationException(// "Some unhandled exception");
return DateTime.Now.ToLocalTime().ToShortTimeString();
}
}
}
TimeSnap.RaiseCallbackEvent() 方法僅返回 string 格式的目前時間。
ASP.NET 2.0 具有一個經過顯著改進的設計器模型,它可以使專業控制項開發人員的工作更加簡單。如果您只是為自己使用而構建一個單個的控制項,該設計器就大材小用了。但是,如果您要為分發而構建一個控制項,您可以使用新的設計器來全面地自訂 Visual Studio 2005 中控制項的行為。
小結
儘管 ASP.NET 2.0 包含了一個內容豐富的擴充控制項集,但開發人員通常有很多理由來建立自訂控制項。由於 ASP.NET 2.0 中的增強功能,建立自訂控制項的過程要比在 ASP.NET 1.x 中更快、更容易。新的 CompositeControl 基類完全利用自適應呈現模型,並為建立複雜的控制項提供了一個簡單、便於使用的容器。如果您的控制項需要回傳或回調功能,ASP.NET 2.0 簡化了處理用戶端指令碼檔案和開發帶外請求的過程。最後,在您開發控制項後,您可以使用各種設計器類來完全配置控制項在視覺化設計工具(例如 Visual Studio 2005)內的行為。