Le problème: j'incorpore un fichier CSS dans une bibliothèque de contrôle personnalisée avec plusieurs contrôles. Je veux partager le même fichier CSS pour tous les contrôles, quel que soit le nombre d'instances sur un formulaire donné. Lorsque plus d'un contrôle est sur le formulaire, je voudrais exactement 1 référence au fichier CSS dans l'en-tête HTML de la page ASP.NET.ASP.NET Custom Control - Quelle est la meilleure façon d'inclure une seule fois une référence CSS incorporée?
Voici ce que je suis venu avec (à ce jour):
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, ça marche ... mais la faille évidente est l'utilisation ici de FindControl()
pour voir si le contrôle existe sur la forme . Bien que j'utilise des conteneurs de dénomination et qu'il semble toujours fonctionner, je suis sûr qu'il y a un moyen de rompre cela. Ajout d'un autre contrôle sur le formulaire avec le même ID est sûrement un ...
La question: Quelle est une meilleure façon de s'assurer que le contrôle d'en-tête est seulement ajouté à l'en-tête HTML une seule fois?
Remarque: La méthode ClientScript.RegisterClientScriptResource()
possède un paramètre qui accepte un type .NET et ce type peut être utilisé pour garantir que le code est uniquement sorti une fois par page. Malheureusement, cette méthode ne fonctionne qu'avec les références de fichiers JavaScript. S'il y a un équivalent intégré pour les références CSS, ce serait ma préférence.
Mise à jour:
j'ai découvert une façon de le faire here un peu plus élégant en utilisant Page.ClientScript.RegisterClientScriptBlock et lui disant que vous incluez vos propres balises de script, mais comme le souligne Rick out, ce n » t ajoute le script à la balise head html et n'est pas non plus compatible xhtml.
Mise à jour 2:
je vis une autre idée intéressante sur this thread, mais une boucle à travers la collection de contrôles n'est pas une très bonne solution et ajoute beaucoup de frais généraux si vous avez plusieurs références et plusieurs contrôles sur la page . Chris Lively a proposé une meilleure solution qui nécessite moins de code. Voici ma fonction altérée avec la nouvelle solution:
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
Un couple de choses à noter à propos de cette solution. Dans son article d'origine, Chris a utilisé la méthode IsClientScriptIncludeRegistered()
qui n'était pas la méthode correspondante à la méthode RegisterClientScriptBlock()
. Pour que cette fonction fonctionne correctement, le test doit être effectué avec IsClientScriptBlockRegistered()
.
En outre, faites très attention au type qui est passé à RegisterClientScriptBlock()
. J'ai passé un type de données personnalisé à cette méthode (le même pour tous mes contrôles), mais il ne s'est pas enregistré de telle sorte que le test IsClientScriptBlockRegistered()
puisse fonctionner. Pour qu'il fonctionne, l'objet Page en cours doit être passé en tant qu'argument Type.
Bien que cette solution ressemble un peu à un hack, elle a) ne nécessite pas beaucoup de code ou de surcharge, b) produit exactement la sortie désirée sur la page, et c) est un code compatible xhtml.
Conceptuellement, pourquoi le css ne fait pas partie du principal fichier css du site qui est récupéré et mis en cache par le client? – jball
Ceci est une bibliothèque de contrôle qui peut théoriquement être utilisée sur n'importe quel site web et je préfère utiliser un CSS séparé (qui peut facilement être surchargé) plutôt que de coder tout le CSS en ligne (comme Microsoft l'a fait dans de nombreux cas). En d'autres termes, mes contrôles doivent être totalement ignorants du site dans lequel ils sont hébergés. – NightOwl888
Le w3validator n'aime pas l'esperluette non codée renvoyée par GetWebResourceUrl. Pour réparer cela encoder l'URL avec Page.Server.HtmlEncode (url) – daniatic