ASP.NET 自定义控件 - 仅包含一次嵌入式 CSS 引用的最佳方法是什么? [英] ASP.NET Custom Control - What is the best way to include embedded CSS reference only once?

查看:13
本文介绍了ASP.NET 自定义控件 - 仅包含一次嵌入式 CSS 引用的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:我将一个 CSS 文件嵌入到一个包含多个控件的自定义控件库中.我想为所有控件共享相同的 CSS 文件,无论它们在给定表单上有多少个实例.当表单上有多个控件时,我希望在 ASP.NET 页面的 HTML 标头中准确地引用 1 个 CSS 文件.

The problem: I am embedding a CSS file into a custom control library with several controls. I want to share the same CSS file for all of the controls regardless of how many instances of them are on a given form. When more than one control is on the form, I would like exactly 1 reference to the CSS file in the HTML header of the ASP.NET page.

这是我想出的(到目前为止):

Here is what I have come up with (so far):

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 的控件肯定是一个...

Ok, it works...but the obvious flaw here is the use of FindControl() to see if the control exists on the form. Although I am using naming containers and it still seems to be working, I am sure there is some way to break this. Adding another control on the form with the same ID is surely one...

问题:有什么更好的方法来确保标题控件只添加到 HTML 标题中一次?

The Question: What is a better way to ensure the header control is only added to the HTML header exactly once?

注意:ClientScript.RegisterClientScriptResource() 方法有一个接受 .NET 类型的参数,该类型可用于确保代码每页仅输出一次.不幸的是,此方法仅适用于 JavaScript 文件引用.如果有 CSS 引用的内置等效项,那将是我的首选.

Note: The ClientScript.RegisterClientScriptResource() method has a parameter that accepts a .NET type and this type can be used to ensure the code is only output once per page. Unfortunately this method only works with JavaScript file references. If there is a built-in equivalent for CSS references, that would be my preference.

更新:

我发现了一种更优雅的方法这里通过使用 Page.ClientScript.RegisterClientScriptBlock 并告诉它您包含自己的脚本标签,但是正如 Rick 指出的那样,这不会将脚本添加到 html 头标签,也不符合 xhtml.

I discovered a slightly more elegant way to do this here by using Page.ClientScript.RegisterClientScriptBlock and telling it you are including your own script tags, however as Rick points out, this doesn't add the script to the html head tag and is also not xhtml compliant.

更新 2:

我在 this thread,但循环遍历控件集合并不是一个很好的解决方案,如果页面上有多个引用和多个控件,则会增加很多开销.

I saw another interesting idea on this thread, but looping through the controls collection is not a very good solution and adds a lot of overhead if you have several references and several controls on the page.

Chris Lively 提出了一个需要更少代码的更好解决方案.这是我使用新解决方案更改的功能:

Chris Lively came up with a better solution that requires less code. Here is my function altered with the new 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

关于此解决方案的几点注意事项.在他的原始帖子中,Chris 使用了 IsClientScriptIncludeRegistered() 方法,该方法不是 RegisterClientScriptBlock() 方法的对应方法.要正确使用此功能,必须使用 IsClientScriptBlockRegistered() 进行测试.

A couple of things to note about this solution. In his original post, Chris used the IsClientScriptIncludeRegistered() method which was not the corresponding method to the RegisterClientScriptBlock() method. To make this function correctly, the test must be done with IsClientScriptBlockRegistered().

另外,请注意传递给 RegisterClientScriptBlock() 的类型.我将自定义数据类型传递给此方法(在我的所有控件中都相同),但它没有以 IsClientScriptBlockRegistered() 测试可以工作的方式注册.为了使其发挥作用,当前的 Page 对象必须作为 Type 参数传入.

Also, pay careful attention to the type that is passed to RegisterClientScriptBlock(). I passed a custom datatype to this method (the same across all of my controls), but it didn't register in such a way that the IsClientScriptBlockRegistered() test would work. In order for it to function, the current Page object must be passed in as the Type argument.

虽然无可否认,这个解决方案感觉有点像 hack,但它 a) 不需要大量代码或开销,b) 在页面上准确生成所需的输出,c) 是 xhtml 兼容代码.

Although admittedly this solution feels a bit like a hack, it a) doesn't require a lot of code or overhead, b) produces exactly the desired output on the page, and c) is xhtml compliant code.

推荐答案

为防止从服务器控件发出 css 文件时出现重复,我们执行以下操作:

To prevent duplication when emitting css files from server controls, we do the following:

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);
}

首先我们测试一下命名脚本是否之前注册过.如果没有,我们添加它.

First we test to see if the named script was previously registered. If not, we add it in.

这篇关于ASP.NET 自定义控件 - 仅包含一次嵌入式 CSS 引用的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆