Asp.net

ASP.NET 自定義控制項 - 僅包含一次嵌入式 CSS 引用的最佳方法是什麼?

  • July 8, 2011

問題:我將一個 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);
}

首先,我們測試該命名腳本是否先前已註冊。如果沒有,我們添加它。

引用自:https://stackoverflow.com/questions/3876601