【關鍵字】代碼重用、用戶控件、@Register指令
ASP.NET提供了比傳統ASP更好的代碼分離方案。在傳統的ASP中,要將用Server. Execute執行的ASP文件或事務對象組件的代碼分離開,一般只能將代碼分離成幾個文件,然后使用“include”的方法。這種方法將造成內存中有多個“include”文件的復本(文件每被引用一次就產生一個復本),從而增加了系統的負擔,因此并不可行。使用Server. Execute或許有些改觀,但是不能向正在執行的ASP文件傳遞附加的查詢串參數。使用組件可能是唯一比較好的做法。在ASP.NET中,除了使用“include”(并不推薦使用)和事務對象組件的方法,還可以使用兩種新技術:code-behind類和WEB用戶控件。
使用code-behind類可以有效地將客戶端的HTML代碼和服務器端的事件處理代碼分離開。將這兩部分代碼分離開有利于調試時跟蹤程序,因為那時就不必在實現用戶界面的代碼和事務邏輯代碼之間來回切換。而且,如果項目中用戶界面和事務處理是由不同的小組開發的,那么使用code-behind類就可以使這兩部分實現獨立調試。利用code-behind類將用戶界面代碼和事務邏輯代碼區分開使得代碼的集成和維護都比較簡便。下面將介紹的用戶控件,從代碼重用的角度來處理代碼分離問題。
1、用戶控件簡介
用戶控件使程序員能夠很容易地跨ASP.NET WEB應用程序劃分和重復使用公共UI功能。與WEB窗體頁相同,程序員可以使用任何文本編輯器創作用戶控件,或者使用代碼隱藏類開發用戶控件。此外,與WEB窗體頁一樣,用戶控件可以在第一次請求時被編譯并存儲在服務器內存中,從而縮短以后請求的響應時間。但與WEB窗體頁不同的是,不能獨立地請求用戶控件,用戶控件必須包括在WEB窗體頁內才能使用。
與服務器端包含文件(SSI)相比,用戶控件通過訪問由ASP.NET提供的對象模型支持,使程序員具有更大的靈活性。程序員可以對在控件中聲明的任何屬性進行編程,而不只是包含其他文件提供的功能,這與其他任何ASP.NET服務器控件一樣。
盡管在創作用戶控件時需要選擇一種語言,但程序員可以將多個用戶控件包含在用多種語言創作的一個WEB窗體頁中。例如,可以用Visual Basic.NET創造一個用戶控件,導入來自XML文件的數據,再用C#創建另一個用戶控件,該控件包含一個訂單窗體,然后在同一個WEB窗體頁中包括這兩個控件。
此外,可以獨立于包含用戶控件的WEB窗體頁中除該控件以外的部分來緩存該控件的輸出。這一技術稱作片段緩存,適當地使用該技術能夠提高站點的性能。例如,如果用戶控件包含提出數據庫請求的ASP.NET服務器控件,但該頁的其余部分只包含文本和在服務器上運行的簡單代碼,則程序員可以對用戶控件執行片段緩存,以改進應用程序的性能。
2、創建用戶控件
可以通過使用文本或HTML編輯器以聲明方式創建用戶控件。用戶控件聲明語法與創建WEB窗體頁所采用的語法十分類似;兩者的主要差別在于用戶控件在內容周圍不包括<html>、<body>和<form>元素。在包含用戶控件的WEB窗體頁中包括這些元素。
用戶控件可以像文本文件一樣簡單,或者它們可以包含其他ASP.NET服務器控件。以下過程簡要介紹了一個可包括在應用程序多個頁上的簡單登錄窗體。
在代碼聲明塊中公開屬性、事件處理程序以及要包括在用戶控件功能中的其他任何代碼。在使用用戶控件的屬性時有兩個選擇。首先,可以定義用戶控件的新屬性并操作它們。其次,可以操作構成用戶控件的服務器控件的屬性。例如,在用戶控件中聲明Textbox WEB服務器控件,并向它提供一個ID為PASSWORD,則可以通過使用PASSWORD. Text語法來操作其Text屬性。
【注意】當用戶控件包括在WEB窗體頁中時,此用戶控件中包含的任何ASP.NET服務器控件的所有屬性和方法都將提升為此用戶控件的公共屬性和方法。
步驟1:以下代碼示例聲明映射到步驟1中代碼的文本框的UserId和Password屬性。可以通過聲明或編程的方式,在任何包含此用戶控件的WEB窗體頁中操作這些屬性。
Public MustInherit Class Loginform Inherits System.Web.UI.UserControl Protected WithEvents User As System.Web.UI.WebControls.TextBox Protected WithEvents Pass As System.Web.UI.WebControls.TextBox Protected WithEvents Button1 As System.Web.UI.WebControls.Button #Region " Web 窗體設計器生成的代碼 " '該調用是 Web 窗體設計器所必需的。 <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() End Sub Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init 'CODEGEN: 此方法調用是 Web 窗體設計器所必需的 '不要使用代碼編輯器修改它。 InitializeComponent() End Sub #End Region Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '在此處放置初始化頁的用戶代碼 End Sub Public Property UserId() As [String] Get Return User.Text End Get Set(ByVal Value As [String]) User.Text = Value End Set End Property Public Property Password() As [String] Get Return Pass.Text End Get Set(ByVal Value As [String]) Pass.Text = Value End Set End Property End Class |
步驟2:創建該用戶控件顯示的UI元素。以下代碼創建與來自步驟1的代碼進行交互的登錄窗體。
【注意】將此用戶控件包括在Web窗體頁中時,需要在@Register指令的Src屬性中包括此文件名稱以及該文件的路徑。
<%@ Control Language="vb" AutoEventWireup="false" Codebehind="Logonform.ascx.vb" Inherits="logintest.Logonform" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %> <TABLE cellSpacing="15"> <TR> <TD><B>用戶姓名: </B></TD> <TD><ASP:TextBox id="User" runat="server"></ASP:TextBox></TD> </TR> <TR> <TD><B>用戶口令: </B></TD> <TD><ASP:TextBox id="Pass" runat="server" TextMode="Password"></ASP:TextBox></TD> </TR> <TR> <TD></TD> <TD><ASP:Button id="Button1" runat="server" Text="登錄" BorderStyle="Groove"></ASP:Button></TD> </TR> </TABLE> |
3、調用用戶控件
只有當包括在WEB窗體頁中時,用戶控件才可以工作。當一個請求到達某一頁而該頁包含用戶控件時,該用戶控件將經歷任何服務器控件所要經歷的所有處理階段。
在 WEB 窗體頁中包括用戶控件的方法很簡單。
在要包含用戶控件的 WEB 窗體頁中,聲明一個@Register指令,該指令包括:
tagprefix屬性,該屬性將前綴與用戶控件相關聯。此前綴將包括在用戶控件元素的開始標記中。
tagname屬性,該屬性將名稱與用戶控件相關聯。此名稱將包括在用戶控件元素的開始標記中。
Src屬性,該屬性定義要包括在WEB窗體頁中的用戶控件文件的虛擬路徑。
例如,以下代碼將注冊在文件LoginForm.ascx中定義的用戶控件。該控件還被指定有標記前綴Acme和標記名稱Login。
<%@ Register TagPrefix="Acme" TagName="LoginForm" Src=".\LoginForm.ascx" %>
使用自定義服務器控件語法在HtmlForm服務器控件的開始標記和結束標記之間 (<form runat=server></form>) 聲明該用戶控件元素。例如,要聲明在上一步導入的控件,使用以下語法。
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="logintest.aspx.vb" Inherits="logintest.WebForm1"%> <%@ Register TagPrefix="Acme" TagName="LoginForm" Src=".\LoginForm.ascx" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>WebForm1</title> <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.0"> <meta name="CODE_LANGUAGE" content="Visual Basic 7.0"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <Acme:LoginForm id=" LoginForm " runat="server"/> </form></BODY> </HTML> |
【注意】無論在WEB窗體頁上包括了多少個ASP.NET服務器控件(用戶控件和其他任何控件),都應只在WEB窗體頁上包括一個HtmlForm服務器控件。此控件的開始和結束標記之間應包括所有服務器控件。
通過上面的程序,在logintest.aspx頁中調用了名為loginform.ascx的用戶控件,結果如下圖所示:
4、用戶控件使用小結
(1)用戶控件使開發人員能夠使用編寫WEB窗體頁的相同編程技巧輕松地定義自定義控件。 作為約定,用.ascx文件擴展名指示這樣的控件。這樣可以確保用戶控件文件不能作為獨立的WEB窗體頁執行。
(2)用戶控件通過Register指令包括在另一WEB窗體頁中,該指令指定TagPrefix、TagName和Src location。
(3)注冊了用戶控件后,可以像普通的服務器控件那樣將用戶控件標記放置在WEB窗體頁中(包括runat="server"屬性)。在包含WEB窗體頁中將用戶控件的公共字段、屬性和方法提升為該控件的公共屬性(標記屬性)和方法。
(4)用戶控件參與每個請求的整個執行生存期,并且可以處理自己的事件,封裝來自包含WEB窗體頁的一些頁邏輯。
(5)用戶控件不應包含任何窗體控件,而應依靠其包含WEB窗體頁在必要時包括窗體控件。
(6)可以使用System.WEB.UI.Page類的LoadControl方法以編程方式創建用戶控件。用戶控件的類型由ASP.NET運行庫決定,遵循約定文件名_擴展名。
(7)只有當為用戶控件包括了Register指令時,用戶控件的強類型才能由包含WEB窗體頁使用(即使沒有實際聲明的用戶控件標記)。
5、結束語
在編寫WEB應用程序時,如果將可能重復出現的元素都用用戶控件來實現,那將大大減少維護代碼的代價。而且在修改代碼時,記得修改一段代碼卻忘了修改另一段同樣代碼的情況也將不存在了。代碼越短,出現錯誤的因素越少,出現錯誤的可能性就越小。