演練:創建 Web 自定義控件
如果現有的 ASP.NET 服務器控件中沒有一個符合應用程序的要求,則可以通過從一個基控件類派生來創建自定義控件。這些類提供服務器控件的所有基本功能,因此您可以將注意力集中在所需功能的編程上。
在本演練中,您將使用自定義 Label 控件的代碼,Web Control Library 模板中默認包括該控件。該控件是從 WebControl 類派生的,其行爲與標準的 Label 控件相同,同時具有添加的屬性將 Text 屬性的值呈現爲超級鏈接。爲了完成本演練,您將執行這些過程:
- 在同一個解決方案中創建兩個項目,一個用於自定義的 Label 控件,一個用於使用和測試該控件的 Web 窗體頁。
- 將該控件添加到工具箱中。
- 通過將自定義控件添加到 Web 窗體頁來使用該控件。
- 爲該控件創建自定義設計器。
- 在瀏覽器中測試該控件。
注意 Visual Basic 和 Visual C# .NET 的標準版沒有提供“Web 控件庫”模板。有關更多信息,請參見 Visual Basic 標準版功能或 Visual C# 標準版的功能。
本演練的重點不是編寫控件的代碼,而是在編寫完代碼後如何生成控件。
創建項目
第一步是使用自定義控件模板開始一個新項目及生成控件。
創建自定義控件
- 在“文件”菜單上指向“新建”,然後單擊“項目”。
將出現“新建項目”對話框。
- 在“項目類型”窗格中選擇“Visual Basic 項目”或“Visual C# 項目”。在“模板”窗格中選擇“Web 控件庫”。
- 將“名稱”更改爲 CustomLabel,然後單擊“確定”。
創建了一個新項目,WebCustomControl1 在代碼編輯器中打開。
默認情況下,自定義 Label 控件的代碼包括在“Web 控件庫”模板中。這是您將在本演練中使用的控件。
- 在“生成”菜單上,單擊“生成 CustomLabel”來編譯控件。
控件編譯爲 CustomLabel.dll。默認情況下,它是在 CustomLabel 項目文件夾的 Bin 文件夾中創建的。
- 保存該文件。
既已創建了該控件,您將一個 Web 窗體頁添加到相同的解決方案,使該頁便於對該控件進行測試。
創建 Web 窗體頁
- 在“文件”菜單上指向“添加項目”,然後單擊“新建項目”。
出現“添加新項目”對話框。
- 在“項目類型”窗格中選擇“Visual Basic 項目”或“Visual C# 項目”。在“模板”窗格中選擇“ASP.NET Web 應用程序”。
- 在“位置”框中,爲應用程序輸入完整的 URL(包含 http:// 和服務器名稱)。URL 的最後一部分是項目的名稱;對於本演練,將項目命名爲 LabelWebForm。Web 服務器上必須安裝 IIS 5 版(或更高版本)和 .NET Framework。如果計算機上已安裝 IIS,可以爲服務器指定
http://localhost
。(如果正常使用代理服務器訪問 Internet,爲了使用本地主機,可能需要配置 Internet Explorer 以繞過代理服務器。) - 單擊“確定”。
創建了新項目,WebForm1 在設計器中打開。
- 保存該項目。
將控件添加到工具箱
既已編譯了控件並具有了可用來測試該控件的 Web 窗體頁,您便可以將該控件添加到工具箱,以便它隨時可供使用。
將控件添加到工具箱
- 在“工具”菜單上,單擊“添加/移除工具箱項”。
- 在“自定義工具箱”對話框的“.NET Framework 組件”選項卡上,單擊“瀏覽”按鈕。查找 CustomLabel.dll,選中它,然後單擊“打開”將 WebCustomControl1 添加到“自定義工具箱”對話框中組件的列表。
- 在 .NET Framework 組件列表中選擇 WebCustomControl1,然後單擊“確定”。WebCustomControl1 被添加到工具箱中。
完成後,您應該看到工具欄上的一個圖標,如下所示:
下一步是在頁中測試該控件。
將控件添加到 Web 窗體頁並測試該控件
- 在“設計”視圖中打開 WebForm1,然後從工具箱中將 WebCustomControl1 拖到該頁上。
控件的默認呈現(僅僅是控件的名稱和其後的控件 ID)出現在“設計”視圖上。
- 切換到“HTML”視圖,然後驗證控件程序集的 @ Register 指令是否已添加到頁的 HTML 中,其 TagPrefix 爲“cc1”。
- 將控件的 Text 屬性設置爲 Hello。
“設計”視圖中控件的外觀被更新以顯示新文本。
然後,您將自定義控件,因此需要將其從工具箱中移除。
從工具箱中移除控件
- 右擊工具箱中的 WebCustomControl1,然後單擊快捷菜單上的“刪除”。該操作將不從項目中刪除控件,只從工具箱刪除控件。
- 關閉該 Web 窗體頁而不保存。
現在自定義 Label 控件可以發揮作用了,但它不是很美觀,並且在代碼中不能明顯區分出該標記。下一步是對控件進行個性化。
個性化控件
該控件正在使用工具箱中的默認圖標,默認的標記前綴是“cc1”。爲了使控件更加便於識別,請更改標記前綴並創建一個新圖標。
更改標記前綴
- 在解決方案資源管理器中 CustomLabel 項目下,雙擊“AssemblyInfo”以在設計器中打開 AssemblyInfo 文件。在 AssemblyInfo 頁的頂部添加 Imports 語句(在 Visual Basic 中)或 using 語句(在 Visual C# 中):
' Visual Basic Imports System.Web.UI // C# using System.Web.UI;
- 將 Assembly: TagPrefix 屬性添加到程序集屬性的列表。這將指定 CustomLabel 控件的新 TagPrefix,在本例中爲 xxx。
' Visual Basic <Assembly: TagPrefix("CustomLabel", "xxx")> //C# [assembly: TagPrefix("CustomLabel", "xxx")]
創建新圖標
- 在解決方案資源管理器中選擇“CustomLabel”項目。在“項目”菜單上單擊“添加新項”。
將出現“添加新項”對話框。
- 在“模板”窗格中選擇“位圖文件”,將“名稱”更改爲 WebCustomControl1.bmp,然後單擊“打開”。新位圖文件出現在解決方案資源管理器中並在設計器中打開。
注意 對於此演練,圖標文件的名稱必須與控件類的名稱 (WebCustomControl1) 完全匹配,包括大小寫。
- 在“屬性”窗口中,將位圖的 Height 和 Width 屬性更改爲 16。圖標的大小必須爲 16 乘 16 像素。
- 在位圖上畫一個獨特的圖案,使用多種顏色,以便您可以識別該圖標。
- 保存並關閉位圖文件。
- 在解決方案資源管理器中選擇 WebCustomControl1.bmp。在“屬性”窗口中,將“生成操作”屬性更改爲“嵌入的資源”。
- 在解決方案資源管理器中選擇“CustomLabel”項目。在“生成”菜單上,單擊“重新生成 CustomLabel”。
- 保存所有的工作。
如果現在將該控件添加到工具箱,則您創建的圖標將顯示在控件名稱的旁邊。當在 Web 窗體頁上使用該控件時,控件的 HTML 標記將包含您指定的標識前綴。
使用自定義控件
- 再次將 WebCustomControl1 添加到工具箱。
顯示控件,帶有您創建的圖標。根據您的設置,它可能顯示在工具箱“常規”選項卡的下面。
- 重新打開名爲 WebForm1 的 Web 窗體頁並將該控件拖到其上。
注意 因爲您先前關閉了 Web 窗體頁而未進行保存,所以 Text 屬性已恢復爲默認值。
- 切換到“HTML”視圖並驗證 @ Register 指令的 TagPrefix 屬性是否爲 xxx。
- 因爲您將對控件進行其他修改,所以從 Web 窗體頁中刪除 WebCustomControl1,但將其保留在工具箱中。
您的自定義控件現在已經完全可用並完成了個性化,但它在設計圖面上的外觀並不是很美觀。要使控件更好看一些,您將向它添加一個自定義設計器。
創建自定義設計器
設計器是允許您修改組件和控件的設計時外觀和行爲的類。雖然所有所見即所得 (WYSIWYG) 窗體設計器的通常目標是儘量減小設計時外觀和運行時外觀之間的差異,但有時也需要特殊的設計時提示。有關更多信息,請參見自定義設計器。
在本演練中,您將實現一個自定義的設計器,該設計器使自定義控件將其文本呈現爲超級鏈接。
創建控件的自定義設計器
- 在解決方案資源管理器中選擇“CustomLabel”項目。
- 在“項目”菜單上,單擊“添加引用”並將引用添加到 System.Design.dll。
- 在“項目”菜單上單擊“添加新項”。
將出現“添加新項”對話框。
- 在“模板”窗格中選擇“類”,將“名稱”更改爲 SampleDesigner,然後單擊“打開”。新的類文件顯示在解決方案資源管理器中,並在設計器中打開。
- 添加代碼,該代碼重寫基類的 GetDesignTimeHtml 方法。設計時調用該方法以獲取控件的表示形式。在重寫的方法中,執行下列操作:
- 獲取自定義控件的 Text 屬性。
- 如果已設置了 Text 屬性(也就是說,它不是一個空字符串),則創建一個新的 Hyperlink 控件,設置其屬性來匹配原始控件,然後調用 Hyperlink 控件的 Render 方法。
最終結果是 Hyperlink 控件使用 Text 屬性的值顯示在設計器中。
執行這些步驟的代碼如下所示,這完整地列出了 SampleDesigner 文件:
' Visual Basic Imports System Imports System.IO Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.Web.UI.Design Public Class SampleDesigner Inherits System.Web.UI.Design.ControlDesigner Public Overrides Function GetDesignTimeHtml() As String ' Component is the control instance, defined in the base ' designer Dim ctl As WebCustomControl1 = CType(Me.Component, _ WebCustomControl1) If (ctl.Text <> "") Then Dim sw As New StringWriter() Dim tw As New HtmlTextWriter(sw) Dim placeholderlink As New HyperLink() ' put control text into the link's Text placeholderlink.Text = ctl.Text placeholderlink.NavigateUrl = ctl.Text placeholderlink.RenderControl(tw) Return sw.ToString() Else Return Me.GetEmptyDesignTimeHtml() End If End Function End Class // C# using System; using System.IO; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.Design; namespace CustomLabel { public class SampleDesigner : System.Web.UI.Design.ControlDesigner { public override string GetDesignTimeHtml() { // Component is the control instance, defined in the base // designer WebCustomControl1 ctl = (WebCustomControl1 ) Component; if (ctl.Text != "" && ctl.Text != null) { StringWriter sw = new StringWriter(); HtmlTextWriter tw = new HtmlTextWriter(sw); HyperLink placeholderLink = new HyperLink(); // put control text into the link's Text placeholderLink.Text = ctl.Text; placeholderLink.NavigateUrl = ctl.Text; placeholderLink.RenderControl(tw); return sw.ToString(); } else return GetEmptyDesignTimeHtml(); } } }
- (根據您正在使用的語言)在設計器中打開 WebCustomControl1.vb 或 WebCustomControl1.cs,然後將該屬性緊接在 WebCustomControl1 類聲明之前添加到屬性列表中:
Designer("CustomLabel.SampleDesigner, CustomLabel")
WebCustomControl1 類聲明應該如下所示:
' Visual Basic <Designer("CustomLabel.SampleDesigner, CustomLabel"), _ DefaultProperty("Text"), ToolboxData("<{0}:WebCustomControl1 _ runat=server></{0}:WebCustomControl1>")> Public Class WebCustomControl1 // C# [Designer("CustomLabel.SampleDesigner, CustomLabel"), DefaultProperty("Text"), ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")] public class WebCustomControl1 : System.Web.UI.WebControls.WebControl
- 在“生成”菜單上,單擊“生成解決方案”,這樣便生成了兩個項目。
- 保存並關閉所有打開的文件。
測試控件
測試 Text 屬性是否正常工作
- 在設計器中打開 WebForm1。
- 將 WebCustomControl1 從工具箱拖到該頁上。
- 將 Web 自定義控件的 Text 屬性設置爲 Hello。該文本控件應該顯示爲 Web 窗體頁上的超級鏈接。
- 保存 WebForm1。
在瀏覽器中測試控件
- 在解決方案資源管理器中選擇 WebForm1。在“文件”菜單上單擊“在瀏覽器中查看”。
- 驗證 Hello 是否顯示在瀏覽器中。文本看起來像一個標籤,而不像超級鏈接。
注意 在 Visual Studio 中,您的代碼在設計時總是完全受信運行的,即使該代碼最終位於一個運行時未受到完全信任的項目中。這意味着當您在自己的計算機上測試自定義控件時,它可能會正確運行,但在部署的應用程序中,該自定義控件可能會因爲權限不足而失敗。務必要在安全上下文(即控件在實際應用程序中運行時所處的上下文)中對您的控件進行測試。