ASP.NET 自定義控制項 - 僅包含一次嵌入式 CSS 引用的最佳方法是什麼?
問題:我將一個 CSS 文件嵌入到一個包含多個控制項的自定義控制項庫中。我想為所有控制項共享相同的 CSS 文件,無論它們在給定表單上有多少個實例。當表單上有多個控制項時,我希望在 ASP.NET 頁面的 HTML 標頭中準確引用 1 個 CSS 文件。
這是我想出的(到目前為止):
Public Sub IncludeStyles(ByVal Page As System.Web.UI.Page) 'Don't include the reference if it already exists... If Page.Header.FindControl("MyID") Is Nothing Then Dim cssUrl As String = Page.ClientScript.GetWebResourceUrl(GetType(Common), StylePath) Dim css As New System.Web.UI.HtmlControls.HtmlGenericControl("link") With css .Attributes.Add("rel", "stylesheet") .Attributes.Add("type", "text/css") .Attributes.Add("href", cssUrl) .ID = "MyID" End With Page.Header.Controls.Add(css) End If End Sub好的,它可以工作……但這裡明顯的缺陷是使用
FindControl()來查看控制項是否存在於表單上。雖然我正在使用命名容器並且它似乎仍然有效,但我確信有一些方法可以打破這一點。在具有相同 ID 的表單上添加另一個控制項肯定是一個……問題:有什麼更好的方法來確保標題控制項只添加到 HTML 標題中一次?
注意:該
ClientScript.RegisterClientScriptResource()方法有一個接受 .NET 類型的參數,該類型可用於確保程式碼每頁僅輸出一次。不幸的是,此方法僅適用於 JavaScript 文件引用。如果有 CSS 引用的內置等效項,那將是我的偏好。更新:
通過使用 Page.ClientScript.RegisterClientScriptBlock 並告訴它您正在包含自己的腳本標籤,我在這裡發現了一種更優雅的方法來執行此操作,但是正如 Rick 指出的那樣,這不會將腳本添加到 html 頭標籤並且也是不符合 xhtml。
更新 2:
我在這個執行緒上看到了另一個有趣的想法,但是循環遍歷控制項集合併不是一個很好的解決方案,如果頁面上有多個引用和多個控制項,則會增加很多成本。
Chris Lively 提出了一個需要更少程式碼的更好的解決方案。這是我使用新解決方案更改的功能:
Public Sub IncludeStyles(ByVal Page As System.Web.UI.Page) If Not Page.ClientScript.IsClientScriptBlockRegistered(StyleName) Then Dim cssUrl As String = Page.ClientScript.GetWebResourceUrl(GetType(Common), StylePath) Dim css As New System.Web.UI.HtmlControls.HtmlGenericControl("link") With css .Attributes.Add("href", cssUrl) .Attributes.Add("rel", "stylesheet") .Attributes.Add("type", "text/css") End With Page.Header.Controls.Add(css) Page.ClientScript.RegisterClientScriptBlock(GetType(Page), StyleName, "") End If End Sub關於這個解決方案有幾點需要注意。在他的原始文章中,Chris 使用了與該
IsClientScriptIncludeRegistered()方法不對應的RegisterClientScriptBlock()方法。要正確使用此功能,必須使用 進行測試IsClientScriptBlockRegistered()。另外,請注意傳遞給
RegisterClientScriptBlock(). 我將自定義數據類型傳遞給此方法(在我的所有控制項中都相同),但它沒有以IsClientScriptBlockRegistered()測試可以工作的方式註冊。為了使其發揮作用,目前的 Page 對象必須作為 Type 參數傳入。雖然無可否認,這個解決方案感覺有點像 hack,但它 a) 不需要大量程式碼或成本,b) 在頁面上準確生成所需的輸出,c) 是 xhtml 兼容程式碼。
為了防止從伺服器控制項發出 css 文件時出現重複,我們執行以下操作:
if (!Page.ClientScript.IsClientScriptBlockRegistered("SoPro." + id)) { HtmlLink cssLink = new HtmlLink(); cssLink.Href = cssLink.Href = Page.ClientScript.GetWebResourceUrl(this.GetType(), styleSheet); cssLink.Attributes.Add("rel", "stylesheet"); cssLink.Attributes.Add("type", "text/css"); this.Page.Header.Controls.Add(cssLink); this.Page.ClientScript.RegisterClientScriptBlock(typeof(System.Web.UI.Page), "SoPro." + id, String.Empty); }首先,我們測試該命名腳本是否先前已註冊。如果沒有,我們添加它。