Das Problem: Ich bette eine CSS-Datei in eine benutzerdefinierte Steuerelementbibliothek mit mehreren Steuerelementen ein. Ich möchte dieselbe CSS-Datei für alle Steuerelemente verwenden, unabhängig davon, wie viele Instanzen von ihnen sich in einem bestimmten Formular befinden. Wenn mehr als ein Steuerelement auf dem Formular ist, möchte ich genau 1 Verweis auf die CSS-Datei in der HTML-Kopfzeile der ASP.NET-Seite.
Hier ist, was ich mir (bisher) ausgedacht habe:
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
Ok, es funktioniert... aber der offensichtliche Fehler hier ist die Verwendung von FindControl()
um festzustellen, ob das Steuerelement auf dem Formular vorhanden ist. Obwohl ich Benennungscontainer verwende und es immer noch zu funktionieren scheint, bin ich sicher, dass es einen Weg gibt, dies zu umgehen. Hinzufügen eines anderen Steuerelements auf dem Formular mit der gleichen ID ist sicherlich eine...
Die Frage: Wie kann man besser sicherstellen, dass das Header-Steuerelement nur genau einmal zum HTML-Header hinzugefügt wird?
Anmerkung: Die ClientScript.RegisterClientScriptResource()
Methode hat einen Parameter, der einen .NET-Typ akzeptiert, und dieser Typ kann verwendet werden, um sicherzustellen, dass der Code nur einmal pro Seite ausgegeben wird. Leider funktioniert diese Methode nur mit JavaScript-Dateiverweisen. Wenn es ein eingebautes Äquivalent für CSS-Referenzen gibt, wäre das meine Präferenz.
Aktualisierung:
Ich habe einen etwas eleganteren Weg gefunden, dies zu tun ici indem Sie Page.ClientScript.RegisterClientScriptBlock verwenden und ihm mitteilen, dass Sie Ihre eigenen Skript-Tags einfügen. Wie Rick jedoch feststellt, fügt dies das Skript nicht zum HTML-Head-Tag hinzu und ist auch nicht xhtml-konform.
Update 2:
Eine weitere interessante Idee habe ich auf dieses Thema Die Schleifenbildung durch die Steuerelementsammlung ist jedoch keine sehr gute Lösung und führt zu einem großen Overhead, wenn Sie mehrere Verweise und mehrere Steuerelemente auf der Seite haben.
Chris Lively hat eine bessere Lösung gefunden, die weniger Code erfordert. Hier ist meine Funktion, die mit der neuen Lösung geändert wurde:
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
Zu dieser Lösung gibt es ein paar Dinge zu beachten. In seinem ursprünglichen Beitrag verwendete Chris die IsClientScriptIncludeRegistered()
Methode, die nicht die entsprechende Methode der RegisterClientScriptBlock()
Methode. Damit dies korrekt funktioniert, muss der Test mit IsClientScriptBlockRegistered()
.
Achten Sie außerdem sorgfältig auf den Typ, der an RegisterClientScriptBlock()
. Ich habe einen benutzerdefinierten Datentyp an diese Methode übergeben (der gleiche für alle meine Steuerelemente), aber er wurde nicht so registriert, dass die IsClientScriptBlockRegistered()
Test funktionieren würde. Damit er funktioniert, muss das aktuelle Seitenobjekt als Argument Type übergeben werden.
Obwohl sich diese Lösung zugegebenermaßen ein wenig wie ein Hack anfühlt, erfordert sie a) nicht viel Code oder Overhead, b) erzeugt sie genau die gewünschte Ausgabe auf der Seite und c) ist der Code xhtml-konform.