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






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

引言
本文解决了从子页面将 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 作为强类型属性传递。
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 缓存功能