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

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

问题描述

问题:我将CSS文件嵌入到具有多个控件的自定义控件库中。我想为所有控件共享同一个CSS文件,而不管它们在给定的表单上有多少个实例。当表单上有多个控件时,我只想在ASP.NET页面的HTML头文件中引用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

好的,它的工作原理...但这里的明显缺陷是使用查找Control()来查看控件是否存在于表单上。虽然我使用命名容器,但仍然似乎正在运行,我相信有一些方法可以打破这个。在表单上添加相同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:

我看到另一个有趣的想法,这个线程,但循环通过控件集合不是非常好的解决方案,并增加了很多开销,如果你有几个参考和页面上的几个控件。

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()方法,这不是与$ code> 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() test将会起作用。为了使其工作,当前的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.

尽管这个解决方案感觉有点像一个黑客,但是它没有不需要大量代码或开销,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天全站免登陆