Controle personalizado do ASP.NET - Qual é a melhor maneira de incluir referência CSS incorporada apenas uma vez?

O problema: estou incorporando um arquivo CSS em uma biblioteca de controle personalizada com vários controles. Desejo compartilhar o mesmo arquivo CSS para todos os controles, independentemente de quantas instâncias deles estejam em um determinado formulário. Quando mais de um controle estiver no formulário, eu gostaria exatamente de 1 referência ao arquivo CSS no cabeçalho HTML da página ASP.NET.

Aqui está o que eu inventei (até agora):

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, funciona ... mas a falha óbvia aqui é o uso deFindControl() para ver se o controle existe no formulário. Embora eu esteja usando contêineres de nomenclatura e ainda pareça estar funcionando, tenho certeza de que há uma maneira de resolver isso. Adicionar outro controle no formulário com o mesmo ID é certamente um ...

A pergunta: Qual é a melhor maneira de garantir que o controle do cabeçalho seja adicionado apenas ao cabeçalho HTML exatamente uma vez?

Note oClientScript.RegisterClientScriptResource() O método tem um parâmetro que aceita um tipo .NET e esse tipo pode ser usado para garantir que o código seja gerado apenas uma vez por página. Infelizmente, esse método funciona apenas com referências de arquivo JavaScript. Se houver um equivalente interno para referências CSS, essa seria minha preferência.

Atualizar:

Eu descobri uma maneira um pouco mais elegante de fazer issoaqui usando Page.ClientScript.RegisterClientScriptBlock e informando que você está incluindo suas próprias tags de script, no entanto, como aponta Rick, isso não adiciona o script à tag de cabeçalho html e também não é compatível com xhtml.

Atualização 2:

Vi outra ideia interessante sobreesta discussão, mas percorrer a coleção de controles não é uma solução muito boa e adiciona muita sobrecarga se você tiver várias referências e vários controles na página.

Chris Lively apresentou uma solução melhor que requer menos código. Aqui está minha função alterada com a nova solução:

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

Algumas coisas a serem observadas sobre esta solução. Em seu post original, Chris usou oIsClientScriptIncludeRegistered() método que não era o método correspondente aoRegisterClientScriptBlock() método. Para fazer esta função corretamente, o teste deve ser realizado comIsClientScriptBlockRegistered().

Além disso, preste muita atenção ao tipo que é passado para oRegisterClientScriptBlock(). Passei um tipo de dados personalizado para esse método (o mesmo em todos os meus controles), mas ele não foi registrado de maneira que oIsClientScriptBlockRegistered() teste funcionaria. Para que ele funcione, o objeto Page atual deve ser passado como o argumento Type.

Embora essa solução pareça um hack, a) não exige muito código ou sobrecarga, b) produz exatamente a saída desejada na página ec) é código compatível com xhtml.

questionAnswers(3)

yourAnswerToTheQuestion