close

Web Application 二部曲:ASP.NET 控制項架構

作者:朱明中

什麼是控制項?

控制項(Control)是一種「使用者介面」的部件,和汽車零件一樣,一個應用程式可以由一個或多個控制項所組成,而這些控制項由元件開發人員或者是程式開發人員另外撰寫,以一個部署單元(deployment unit)構成,例如一個 OCX,或是以一個 DLL 的方式形成。

控制項是由一組可完成控制項提供之服務的程式碼、資源(如字串、圖片或其他資料)、以及其他必要資訊(例如安裝資訊檔或是部署資料檔)包裝而成,每個控制項都有它的一個開放介面、功能或是服務,應用程式開發人員可以利用這些介面來操作控制項,來達成使用者介面、應用程式功能等設計。

但控制項本身受限於其類型(自訂控制項或是使用者控制項)、功能範圍與介面等限制,有時候系統提供的控制項無法達到預期的效用,此時就必須要尋找另外的控制項,或是自行打造所需要的控制項。

元件和控制項的不同

元件(Component)是一種程式碼的集合,和控制項一樣,提供介面來讓應用程式使用,但元件並沒有使用者介面,而控制項是有使用者介面的元件,而且控制項可以直接在應用程式整合開發介面(Integrated Development Environment, IDE)-如 Visual Studio 2005 IDE -部署到應用程式中的,也就是說,控制項會提供與 IDE 連接與溝通的介面(例如事件,屬性列表等),但元件則不一定會提供。

以 Microsoft .NET 來說,元件是以繼承與實作 IComponent 介面(提供元件基礎架構)的類別程式碼,而在控制項部份,則是以繼承 System.Windows.Forms.Control(Windows 控制項)或是 System.Web.UI.Control(Web 控制項)的類別程式碼稱之,而 System.Windows.Forms.Control 與 System.Web.UI.Control 都有實作 IComponent 介面,所以控制項是屬於 .NET 元件的一部份,也擁有 .NET 元件的基礎功能。

ASP.NET 控制項類型

ASP.NET 的控制項因為類型與適用的不同,分為三種控制項:

  • ASP.NET 內建控制項(Built-in Control):由 Web Server 控制項與 HTML Server 控制項所組成,為 ASP.NET 提供的基本控制項服務,包含按鈕、核取方塊、選項按鈕、連結、文字方塊、驗證控制項(Validation Control)、Tree View、Menu、Multi-View、Grid-View 等等。
  • ASP.NET 使用者控制項(User Control):這是一個很簡單的複合型控制項(Composite Control),由 HTML 組成,可以把它當成小型的 ASP.NET 網頁,開發人員可以簡單的使用 HTML 組合發展,它可以被許多頁面重覆使用,但其適用的範圍只在 ASP.NET 網站專案本身而已,而且它無法自訂繪製控制項的能力。
  • ASP.NET 自訂控制項(Custom Control):這是一個具有可跨越專案,高度重覆使用性(Reusability)的控制項,它給程式開發人員更多可以揮灑的空間,並且有更多與 IDE 溝通的方法,以及幾近完全自訂的繪製能力(customized rendering),也因為這麼強的能力,讓開發自訂控制項變得複雜許多,也更花費開發人員的心力。
ASP.NET User Control 以 .ascx 為副檔名,而 ASP.NET Custom Control 則是以二進位的 DLL 組件存在。

ASP.NET 控制項架構(Control Architecture)

前面已經提及了,控制項是一種使用者介面的元件,換言之,它必須要有輸出使用者介面指令的能力,依照前一期的文章所說明,ASP.NET 的使用者介面是一種 HTML 與 scripting 的指令,控制項必須要有能力產生這些指令,讓 ASP.NET 輸出到用戶端,這樣使用者才看的到控制項的介面。

繪製(Rendering)在 ASP.NET 的術語來說,是一種產生 HTML 和 scripting 指令的程序,使用者控制項的繪製是由 ASP.NET User Control 類別進行繪製工作,把內含在 User Control 內的控制項與頁面繪製成 HTML 再輸出,所以 User Control 的基本繪製程序如圖 1。

而自訂控制項則可以透過實作 Render 相關函式的方式,決定要輸出的使用者介面指令,輸出的範圍包含了標籤、屬性與值等資料,但開發自訂控制項的人員必須要熟悉 HTML(與 scripting)的能力,才能知道要如何正確的輸出指令。

protected override void AddAttributesToRender( HtmlTextWriter writer) 
{ 
    base.AddAttributesToRender(writer); 
    writer.AddAttribute(HtmlTextWriterAttribute.Href, "mailto:" +
    Email);
} 
protected override void RenderContents(HtmlTextWriter writer) 
{ 
    if (Text == String.Empty) 
    { 
        Text = Email; 
    } 
    writer.WriteEncodedText(Text); 
}

與繪製一樣重要的部份,就是資料交換(Data Exchange)的能力,控制項必須要能夠接受使用者輸入與保存資料,而保存資料在 ASP.NET 中則是一個重要的課題。

還記得前一篇文章的「ASP.NET 不會『主動』幫你記住任何東西」這句話嗎?這在 Web Application 發展時,是必須要記住的鐵律,而控制項發展時,處處都要實作資料保存的狀態(其實不只是控制項,頁面也會需要這樣的能力),通常控制項都會使用 Control State(.NET Framework 2.0 才有的)或是 View State 來協助資料的保存,讓使用者在每次頁面進行 Post Back 時,可以讓控制項保持住資料與控制項的狀態。

Post Back 是一種資料交換的方法,在 ASP.NET 繪製階段產生的 HTML 中,有部份 HTML 指令是以未編碼或編碼方式保存資料的指令,例如 <input type= "hidden" value= "…" /> 這樣的,透過 Client 下指令與 Server 溝通時,會透過 HTTP POST 的通訊協定傳至 Server,ASP.NET 執行引擎會接取這些資料,並交給控制項來做處理,並且再將結果繪製到輸出的 HTML 中。

透過Render -> Client -> Post Back -> Process -> Render 的步驟,組合成整個 ASP.NET 運行的架構。

如果讀者有使用過 JSP (Java Server Pages) 的話,也許有聽過一個名詞:Tag Library,Tag Library 在 ASP.NET 來說就是每個伺服器控制項。

ASP.NET 控制項事件模型

不管是 ASP.NET 本身或是 ASP.NET 的控制項的事件,它們的背後都會有 Post Back 的影子,有些可能用不到 Post Back,但是若要讓伺服器有作用時,就必須要傳遞指令給 Server,才能驅動 Server 的指令,例如 Button 的 OnClick 事件,Button 本身在解譯成 HTML 時會變成 <input type= "submit" /> 指令,讀者可以觀察一下它的 onclick 事件常式,它會呼叫一個由 ASP.NET 指令碼提供的函式,用來處理 Post Back 引發的工作。

在一個 ASP.NET 網頁中,都常會看到這樣的 JavaScript 的指令碼:

function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}

常寫 ASP.NET 網頁程式的讀者可能會眼睛一亮,因為看到了二個熟悉的參數 - eventTarget 與 eventArgument - 它們會對應到事件常式的 sender 與 e 這二個參數,而這個參數的轉換都被 ASP.NET 在背後做掉了,而程式員只要在程式中下這樣的語法,就可以知道事件是由什麼控制項所發出的:

// C#
private void Button1_OnClick(object sender, EventArgs e)
{
   Button senderObj = sender as Button;
   // do something you want.
}
‘ Visual Basic
Private Sub Button_OnClick(sender As Object, e As EventArgs)
    Dim button as Button
    Button = CType(sender, Button)
   ‘ do something you want.
End Sub

暫且運筆至此,下回筆者來說說 Web Application 中的動態機制-也就是動態控制項生成的能力。

arrow
arrow
    全站熱搜

    羅 朝淇 發表在 痞客邦 留言(0) 人氣()