Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ASP.NET自定义控件-仅包含一次嵌入式CSS引用的最佳方法是什么?_Asp.net_Css_Dependencies_Custom Server Controls - Fatal编程技术网

ASP.NET自定义控件-仅包含一次嵌入式CSS引用的最佳方法是什么?

ASP.NET自定义控件-仅包含一次嵌入式CSS引用的最佳方法是什么?,asp.net,css,dependencies,custom-server-controls,Asp.net,Css,Dependencies,Custom Server Controls,问题是:我正在将一个CSS文件嵌入到一个带有多个控件的自定义控件库中。我想为所有控件共享相同的CSS文件,而不管给定表单上有多少个控件实例。当表单上有多个控件时,我希望ASP.NET页面的HTML标题中正好有一个CSS文件引用 以下是我(到目前为止)得出的结论: 好的,它可以工作……但是这里明显的缺陷是使用FindControl()查看表单上是否存在该控件。虽然我正在使用命名容器,而且它似乎仍在工作,但我确信有某种方法可以打破这种局面。在窗体上添加另一个具有相同ID的控件肯定是一个 问题是:有什

问题是:我正在将一个CSS文件嵌入到一个带有多个控件的自定义控件库中。我想为所有控件共享相同的CSS文件,而不管给定表单上有多少个控件实例。当表单上有多个控件时,我希望ASP.NET页面的HTML标题中正好有一个CSS文件引用

以下是我(到目前为止)得出的结论:

好的,它可以工作……但是这里明显的缺陷是使用
FindControl()
查看表单上是否存在该控件。虽然我正在使用命名容器,而且它似乎仍在工作,但我确信有某种方法可以打破这种局面。在窗体上添加另一个具有相同ID的控件肯定是一个

问题是:有什么更好的方法可以确保头控件只添加到HTML头中一次

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

更新:

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

更新2:

我在上看到了另一个有趣的想法,但是在控件集合中循环不是一个很好的解决方案,如果页面上有多个引用和多个控件,那么会增加很多开销

ChrisLively提出了一个需要更少代码的更好的解决方案。以下是我使用新解决方案更改的功能:

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()
完成测试

另外,请仔细注意传递给
RegisterClientScriptBlock()
的类型。我向这个方法传递了一个自定义数据类型(在我所有的控件中都是一样的),但是它的注册方式没有使
isclientscriptblockregisted()
测试能够工作。为了使其正常工作,必须将当前页面对象作为类型参数传入


尽管不可否认,这种解决方案感觉有点像黑客,但它a)不需要大量代码或开销,b)在页面上生成所需的输出,c)是与xhtml兼容的代码。

为什么不在控件中创建一个私有布尔变量,在最初创建CSS时将其设置为true。然后,您可以在调用该方法时进行检查,以查看是否已经设置了css。下面的例子(我的VB生锈了,所以可能有点错误)


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

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

首先,我们测试命名脚本是否以前注册过。如果没有,我们就添加它。

我不知道为什么,但您的解决方案对我不起作用,ClientScript.IsClientScriptBlockRegistered调用始终返回false。但是John Bledsoe关于您已经提供的链接()的建议对我有效:

public static void IncludeStylesheet(Page page, string href, string styleID)
{
    //Prevent the stylesheet being included more than once
     styleID = "_" + styleID;
    if (HttpContext.Current.Items[styleID] == null)
    {
        HtmlLink htmlLink = new HtmlLink();
        htmlLink.Href = href;
        htmlLink.Attributes.Add("rel", "stylesheet");
        htmlLink.Attributes.Add("type", "text/css");
        page.Header.Controls.Add(htmlLink);
        HttpContext.Current.Items[styleID] = true;
    }
}

从概念上讲,为什么css不是客户端获取和缓存的网站主css文件的一部分?这是一个理论上可以在任何网站中使用的控制库,我更喜欢使用单独的css(可以轻松覆盖),而不是硬编码所有css内联(就像Microsoft在许多情况下所做的那样)。换句话说,我的控件应该完全不知道它们所在的站点。w3validator不喜欢GetWebResourceUrl返回的未编码的符号。若要修复此问题,请使用Page.Server.HtmlEncode(url)对url进行编码将无法工作。首先,您将变量设置为private,这意味着每个控件实例都有一个单独的副本。一个共享变量可能会在不同的用户之间出现问题,所以这也不起作用。这个想法很有趣,起初我认为它会起作用。但是,我试过了,有几个问题(除非我错过了什么)。这将在mime类型“text/javascript”下注册CSS。此外,它创建一个“脚本”标记,而不是“链接”标记。第三,虽然没有那么重要,但是标记不包括在document.Oops的头部。错误的片段。再看看,好主意!我在原来的帖子中添加了一个更正版本。测试必须使用RegisterClientScriptBlockInclude完成,但除此之外,这段代码工作得很好。@NightOwl888:谢谢您找到它。我正在更新我们自己的代码库。这也是一个有趣的想法。我不知道为什么我以前没有想到使用HttpContext.Items。但是谢谢分享。
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);
}
public static void IncludeStylesheet(Page page, string href, string styleID)
{
    //Prevent the stylesheet being included more than once
     styleID = "_" + styleID;
    if (HttpContext.Current.Items[styleID] == null)
    {
        HtmlLink htmlLink = new HtmlLink();
        htmlLink.Href = href;
        htmlLink.Attributes.Add("rel", "stylesheet");
        htmlLink.Attributes.Add("type", "text/css");
        page.Header.Controls.Add(htmlLink);
        HttpContext.Current.Items[styleID] = true;
    }
}