65.9K
CodeProject 正在变化。 阅读更多。
Home

将 JavaScript/CSS 作为用户控件从子页面包含到母版页中

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (3投票s)

2010 年 4 月 11 日

CPOL

5分钟阅读

viewsIcon

55508

downloadIcon

353

本文介绍了一种将 JavaScript/CSS 作为用户控件从子页面、包含在子页面中的用户控件、包含在子页面中的 Web 控件包含到母版页中的方法。

JsUserControl.jpg

引言

本文解决了从子页面将 JavaScript 和 CSS 样式包含到母版页的节中的问题。虽然有很多文章和帖子处理过这个问题,但到目前为止,作者还没有找到一个令人满意的解决方案来处理将“客户端 ID”传递给包含的 JavaScript 文件。本文还解决了使包含的脚本具有语法高亮显示的问题。

背景

众所周知,有很多方法可以将 JavaScript 包含到母版页的 head 节中。这可以轻松完成,例如,使用内置的 'RegisterClientScriptInclude'、'RegisterStartupScript' 或 'RegisterClientScriptBlock' 方法。后两个方法的缺点是必须从代码隐藏中以纯字符串的形式进行,并且无法获得语法高亮显示。虽然对于使用 'RegisterClientScriptInclude' 方法包含的脚本,我们可以使用语法高亮显示,但我们无法将客户端 ID 传递给它!Rick Strahl 在 ['http://www.west-wind.com/weblog/posts/252178.aspx'] 中处理了传递客户端 ID 的问题。CodeProject 上也有一篇文章 [https://codeproject.org.cn/KB/aspnet/resource_files_in_asp_net.aspx?display=Print] 尝试通过将 JavaScript 存储在资源文件中来解决此问题。[http://www.dougv.com/blog/2010/02/17/dynamically-adding-javascript-to-your-asp-net-master-page-from-a-child-page/] 审查了解决此问题的常见方法并提出了解决方案。

我的解决方案

本文作者提出的解决方案实现了以下功能:

  • 从子页面将 JavaScript 和 CSS 放置到母版页的 head 节或 <\form > 标签结束之前。
  • 包含的脚本具有 JavaScript 和 CSS 语法高亮显示。
  • 客户端 ID 作为强类型属性传递。
所有这三个功能都是通过使用包含我们的 JavaScript 和 CSS 的用户控件来实现的。用户控件可以从子页面动态加载到母版页的任何占位符中。我们通过控件的 public 属性将客户端 ID 传递给 JavaScript。如果占位符放置在 head 节中,我们就实现了 'RegisterClientScriptInclude' 和 'RegisterClientScriptBlock' 方法的等效功能。如果放置在母版页的 <\form > 标签之前,我们就模仿了 'RegisterStartupScript' 方法的功能。

理解代码

示例应用程序演示了四种不同的方式来包含 JavaScript 和 CSS:

  • 从子页面“default.aspx”将 JavaScript /CSS 包含到母版页“Master.master”中(在 <\form > 标签结束之前)。这等同于“RegisterStartupScript”方法。
  • 从子页面“default.aspx”将 JavaScript /CSS 包含到母版页“Master.master”中(放入 head 节)。这等同于“RegisterClientScriptBlock/RegisterClientScriptInclude”方法。
  • 从包含在子页面“default.aspx”中的 Web 控件“WebControl.cs”将 JavaScript /CSS 包含到母版页“Master.master”中(放入 head 节)。这等同于“RegisterStartupBlock/RegisterClientScriptInclude”方法。
  • 从包含在子页面“default.aspx”中的用户控件“WebUserControl.ascx”将 JavaScript /CSS 包含到母版页“Master.master”中(放入 head 节)。这等同于“RegisterStartupBlock/RegisterClientScriptInclude”方法。

在这四种情况下,我们都有输入表单。包含的 JavaScript(例如,在第一种情况下的用户控件“CtrWithJs.ascx”中)负责读取表单内容并在屏幕上显示。我们将输入字段 ID 通过其属性传递给控件。表单的样式通过包含在“CtrWithJs.ascx”控件中的 CSS 来实现。

Using the Code

代码使用非常简单。“default.aspx”页面动态加载两个用户控件“CtrWithJs2.ascx”和“CtrWithJs.ascx”,其中包含 JavaScript/CSS,到“Master.master”页面中。这是在子页面“default.aspx”的“Page_PreRender”中完成的。对于前者,我们将“CtrWithJs2.ascx”加载到“ContentPlaceHolder2”中,放在 <\form > 标签之前;对于后者,我们直接将其加载到母版页的头部,并使用“runat”属性。正如我们所见,所有“客户端 ID”都通过属性传递。

protected void Page_PreRender(object sender, EventArgs e)
{
    var ctrlWithJs = (CtrWithJs)LoadControl("CtrWithJs.ascx");
    var ctrlWithJs2 = (CtrWithJs2)LoadControl("CtrWithJs2.ascx");

    ctrlWithJs.textBox1Id = txt1.ClientID;
    ctrlWithJs.textBox2Id = txt2.ClientID;
    ctrlWithJs2.textBox3Id = txt3.ClientID;
    ctrlWithJs2.textBox4Id = txt4.ClientID;

    Master.Page.Header.Controls.Add(ctrlWithJs);
    var bottomPl = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder2");

    bottomPl.Controls.Add(ctrlWithJs2);
}

有时,我们可能会在页面上使用用户控件,例如“WebUserControl.ascx”。在这种情况下,用户控件本身会将我们的容器用户控件“CtrWithJs4.ascx”动态加载到母版页的 head 节等位置,即:

protected void Page_PreRender(object sender, EventArgs e)
{
    var ctrlWithJs4 = (CtrWithJs4)LoadControl("CtrWithJs4.ascx");

    ctrlWithJs4.textBox11Id = WebUserControltxt1.ClientID;
    ctrlWithJs4.textBox12Id = WebUserControltxt2.ClientID;

    Page.Master.Page.Header.Controls.Add(ctrlWithJs4);
}

如果我们想使用 Web 控件,例如“WebControl.cs”,它会加载自己的 JavaScript/CSS,该怎么做?方法几乎相同。

protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);

    Control ctrlWithJs3 = Page.LoadControl("CtrWithJs3.ascx");

    ((IClientIdInterface3)ctrlWithJs3).textBox1Id = txtBox1.ClientID;
    ((IClientIdInterface3)ctrlWithJs3).textBox2Id = txtBox2.ClientID;

    Page.Master.Page.Header.Controls.Add(ctrlWithJs3);
}

正如我们所见,我们在如何将客户端 ID 传递给 JavaScript/CSS 容器控件“CtrWithJs3.ascx”时遇到了一些小问题。为了实现这一点,容器用户控件实现了一个接口“IClientIdInterface3”,

public interface IClientIdInterface3
{
    string textBox1Id { get; set; }
    string textBox2Id { get; set; }
}

该接口仅包含用于传递客户端 ID 的 string 属性,

using System;
public partial class CtrWithJs3 : System.Web.UI.UserControl, IClientIdInterface3
{
    public string textBox1Id { get; set; }
    public string textBox2Id { get; set; }
}

容器用户控件包含语法高亮显示的 JavaScript/CSS。

<%@ Control Language="C#" AutoEventWireup="true" 
	CodeFile="CtrWithJs3.ascx.cs" Inherits="CtrWithJs3" % >
<script type="text/javascript">

    function ReadTTxt5() {
        var inputParam = '<%=textBox1Id%>';
        alert(document.getElementById(inputParam).value);
    }
    function ReadTTxt6() {
        var inputParam = '<%=textBox2Id%>>';
        alert(document.getElementById(inputParam).value);
    }
</script>
<link rel="Stylesheet" href="StyleSheet3.css" title="Contemporary" />

JavaScript/CSS 缓存

为了利用浏览器对 JavaScript/CSS 的缓存,我们可以将上述“CtrWithJs3.ascx”的 JavaScript 容器用户控件重写如下,

<%@ Control Language="C#" AutoEventWireup="true"  CodeFile="CtrWithJs3.ascx.cs" 
    Inherits="CtrWithJs3" % > 
<script type="text/javascript">
    var inputParam5 = '<%=textBox1Id%>';
    var inputParam6 = '<%=textBox2Id%>';
</script>
<script type="text/javascript" src="WebUserConrolScript.js" ></script>
<link rel="Stylesheet" href="StyleSheet3.css" title="Contemporary" />
其中“WebUserConrolScript.js”具有以下形式:
     function ReadTTxt5() {
     alert(document.getElementById(inputParam5).value);
    }
    function ReadTTxt6() {
     alert(document.getElementById(inputParam6).value);
    }
并且将被浏览器缓存。 "StyleSheet3.css" 样式表也将被缓存。

结论

正如“背景”部分所述,本文处理的问题在许多互联网论坛上已被无数次讨论过。本文作者认为独特之处在于使用用户控件作为 JavaScript 和 CSS 的容器。通过这样做,我们可以获得语法高亮显示,并且可以将客户端 ID 作为强类型属性进行传递。我们在本文中展示了,这可以从常规子页面、子页面上使用的用户控件、子页面上使用的 Web 控件来实现。包含的 JavaScript 文件和 CSS 样式也会被浏览器缓存。

历史

  • 2010 年 4 月 11 日:初始版本
  • 2010 年 4 月 22 日:添加 JavaScript 缓存功能
© . All rights reserved.