asp.net 提供一种很好的模块级的复用技术 ―― 用户控件,大大方便了 web 网站的建设,提高了效率。用户控件使用多了,碰到的问题也会增多。最近遇到一个问题,就是如果在一个用户控件中要使用到客户端脚本,而这个客户端的脚本又要访问到控件中包含的控件,问题就出现了。问题是当一个用户控件被包含到一个 aspx 页面后,呈现到用户客户端后,整个用户控件中的控件的名称将会有所变化,它们不再是你设计这个用户控件时的名称,而是有两个相关的名称:
** id ** ―― 客户端可以通过这个 id 访问这个客户端控件, asp.net 给每个控件输出的 id 形式为“用户控件 id_ 此控件的 id ”,如果是用户控件嵌套的情况,形式为“顶层用户控件 id_ 下层用户控件 id_ 此控件的 id ”
** name ** ―― 客户端也可以通过这个 name 来访问这个客户端控件, asp.net 给每个控件输出的 name “用户控件 id: 此控件的 id ”,如果是用户控件嵌套的情况,形式为“顶层用户控件 id: 下层用户控件 id: 此控件的 id ”。
例子:
1<input id="WebUserControl11_TextBox1" name="WebUserControl11:TextBox1" type="text"/>
在设计用户控件时,放置了一个 TextBox , id 为 TexBox1 ,这个用户控件被放置到一个 aspx 页面,用户控件的 id 为 WebUserControl11 ,最后这个用户控件的 TextBox 到客户端后就是上面的这个样子的了。
客户端提交到服务端时是根据控件的 name 来提交的,也就是说,对服务端来讲,客户端的name是有意义的, id 是不需要的。
在写客户端脚本时你不能预知你的用户控件将会是以什么 id 加入到 aspx 页面的,也不能预知用户控件被嵌套了多少层,所以你根本不能在设计时来参考这些控件。
幸好, asp.net 的 webcontrol 和 htmlcontrol 的控件有个运行时属性 UniqueID ,用来获取服务器控件的唯一的、以分层形式限定的标识符。对应到上面的那个例子,控件 TextBox1 的 UniqueID 就是“ WebUserControl11:TextBox1 ”,跟生成的客户端的控件的 name 相一致。
所以我们可以用控件的 UniqueID 来获得运行时客户端的 name ,也就能通过这个 name 来控制客户端控件了。
OK ,按照这个思路来设计个客户端脚本:
用户控件很简单,就放置一个 TextBox ,我们再给这个 TextBox 设置一个鼠标经过事件来触犯客户端的脚本,给 TextBox 赋一个值,代码如下:
1@ Control Language="c#" AutoEventWireup="false" Codebehind="WebUserControl1.ascx.cs" Inherits="WebApplication3.WebUserControl1" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"
1<asp:textbox id="TextBox1" onmouseover="over()" runat="server"></asp:textbox>
1<script language="javascript">
2
3<!--
4
5function over()
6
7{
8
9document.all.```
10= TextBox1. UniqueID
11```.value = "kent";
12
13}
14
15//-->
16
17</script>
将这个用户控件拖放到一个 aspx 页面中,编译浏览这个页面,报一个脚本错误: 缺少‘;’ ** **
把鼠标移到 TextBox 时,又报一个脚本错误:“ 缺少对象 ”
检查发现,客户端引用的标示不能含有 ”:” 符号,就是说在客户端不能用控件的 name 来参考。 asp.net 的 webcontrol 和 htmlcontrol 的控件还有个运行时属性 ClientID ,它用来获取由 ASP.NET 生成的服务器控件标识符,也就是来获取控件的客户端 id 的,我们再改用这个属性来试一下:
document.all.``` = TextBox1.ClientID
1
2再运行, OK 成功,当鼠标移动 TextBox 时, TextBox 中出现了“ kent ”。