Пользовательский элемент управления ASP.NET - Как лучше всего включить ссылку на встроенный CSS только один раз?

Проблема: Я встраиваю файл CSS в библиотеку настраиваемых элементов управления с несколькими элементами управления. Я хочу использовать один и тот же файл CSS для всех элементов управления, независимо от того, сколько их экземпляров находится в данной форме. Когда в форме присутствует более одного элемента управления, я хотел бы получить ровно одну ссылку на файл CSS в заголовке HTML страницы ASP.NET.

Вот что я придумал (пока):

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 () , чтобы увидеть, существует ли элемент управления в форме. Хотя я использую именование контейнеров, и он все еще работает, я уверен, что есть способ сломать это. Добавление еще одного элемента управления в форму с тем же идентификатором, безусловно, является одним ...

Вопрос: как лучше гарантировать, что элемент управления заголовком добавляется в заголовок HTML только один раз?

Примечание: ] ClientScript. Метод RegisterClientScriptResource () имеет параметр, который принимает тип .NET, и этот тип можно использовать для обеспечения того, чтобы код выводился только один раз на страницу. К сожалению, этот метод работает только со ссылками на файлы JavaScript. Если есть встроенный эквивалент для ссылок CSS, я бы предпочел это.

Обновление:

Я обнаружил немного более элегантный способ сделать это здесь с помощью Page.ClientScript.RegisterClientScriptBlock и сообщая ему, что вы включаете свои собственные теги сценария, однако, как указывает Рик, это не добавляет сценарий к тегу заголовка html и также несовместим с xhtml.

Обновление 2:

Я увидел еще одну интересную идею в этой ветке , но цикл по коллекции элементов управления - не очень хорошее решение и добавляет много накладных расходов, если у вас есть несколько ссылок и несколько элементов управления на странице.

Крис Лайвли предложил лучшее решение, которое требует меньше кода. Вот моя функция, измененная с помощью нового решения:

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

Несколько замечаний об этом решении. В своем исходном сообщении Крис использовал метод IsClientScriptIncludeRegistered () , который не соответствовал методу RegisterClientScriptBlock () . Чтобы эта функция работала правильно, проверка должна выполняться с помощью IsClientScriptBlockRegistered () .

Также обратите особое внимание на тип, который передается в RegisterClientScriptBlock () . Я передал этому методу пользовательский тип данных (одинаковый для всех моих элементов управления), но он не зарегистрировался таким образом, чтобы тест IsClientScriptBlockRegistered () работал. Для его функционирования текущий объект Page должен быть передан в качестве аргумента Type.

Хотя, по общему признанию, это решение немного похоже на взлом, оно а) не требует большого количества кода или накладных расходов, б) производит именно тот результат, который требуется на странице, и c) является xhtml-совместимым кодом.

9
задан Community 23 May 2017 в 02:09
поделиться