母版页中对控件ID的处理

简介:
本篇技巧和诀窍记录的是:母版页中对控件ID的处理。
  一、问题提出
  由于总体排版和设计的需要,我们往往创建母版页来实现整个网站的统一性,最近我由于统一性的需要,把原来整个项目单独的页面全部套用了母版页。但是出现了一个错误……在我的Blog中记录一下,方便大家参考。
  二、 抽象模型
  由于整个页面内容过多,所以我把这个页面中最为本质的问题抽象出来。原来单一页面,就是利用按钮触发JS事件,在文本域中插入“(_)”功能,其实现代码如下:
  <head id="Head1" runat="server">
  <title>单一页面抽象模型-YJingLee</title>
  <script language="javascript" type="text/javascript">
  // <!CDATA[
  function insert() {
  document.getElementById("txt").value=document.getElementById("txt").value+"(__)";
  return;
  }
  // ]]>
  </script>
  </head>
  <body>
  <form id="form1" runat="server">
  <div>
  <textarea id="txt" runat="server" name="txt" rows="10" cols="50"></textarea>
  <asp:Button ID="btnInsert" runat="server" Text="服务器端插入(_)" OnClientClick="insert();" />
  <input id="btnInsert2" name="insert" onclick="insert();" type="button" value="客户端插入(_)"
  runat="server" /></div>
  </form>
  </body>
  </html>上述页面可以正常使用。后来使用模板页后,其代码如下:
  <asp:content id="Content1" contentplaceholderid="ContentPlaceHolder1" runat="Server">
  <script language="javascript" type="text/javascript">
  // <!CDATA[
  function insert() {
  document.getElementById("txt").value = document.getElementById("txt").value + "(__)";
  return;
  }
  // ]]>
  </script>
  <div>
  <textarea id="txt" runat="server" name="txt" rows="10" cols="50"></textarea>
  <asp:Button ID="btnInsert" runat="server" Text="服务器端插入(_)"  OnClientClick="insert();"/>
  <input id="btnInsert2" name="insert" onclick="insert();" type="button"        value="客户端插入(_)" runat="server"/></div>
  </asp:content>当打开后按下按钮出现了“Microsoft JScript 运行时错误: 'document.getElementById(...)' 为空或不是对象”。这是什么原因呢?原来好好的,怎么套用个母版页就出现这个奇怪的问题呢?困扰了好久,和朋友讨论了一下,终于找到了答案……
  三、分析本质
  原来我们仔细看看其生成的HTML代码:单一页面:
  <form name="form1" method="post" action="Default.aspx" id="form1">
  <textarea name="txt" id="txt" rows="10" cols="50"></textarea>
  <input type="submit" name="btnInsert" value="服务器端插入(_)" onclick="insert();" id="btnInsert" />
  <input name="btnInsert2" type="button" id="btnInsert2" onclick="insert();" value="客户端插入(_)" />
  </form>再看看套用母版页之后,生成的HTML代码:
  <form name="aspnetForm" method="post" action="Default2.aspx" id="aspnetForm">
  <textarea name="ctl00$ContentPlaceHolder1$txt" id="ctl00_ContentPlaceHolder1_txt"
  rows="10" cols="50"></textarea>
  <input type="submit" name="ctl00$ContentPlaceHolder1$btnInsert" value="服务器端插入(_)"
  onclick="insert();" id="ctl00_ContentPlaceHolder1_btnInsert" />
  <input name="ctl00$ContentPlaceHolder1$btnInsert2" type="button"          id="ctl00_ContentPlaceHolder1_btnInsert2"
  onclick="insert();" value="客户端插入(_)" />
  </form>是不是看到问题了,源文件控件元素的ID和生成HTML文件的ID不一致。表单from的name属性和id属性变成了aspnetForm,控件的id属性被无缘无故了加上了ctl00_ContentPlaceHolder1_前缀,其name属性也加上了ctl00$ContentPlaceHolder1$前缀。
  这下知道了,难怪提示“'document.getElementById(...)' 为空或不是对象”的错误了,原来生成页面后其ID都变了。那么我们如何解决它呢?既然他id变了,我们就把JS代码id改为生成后的id。代码如下:
  function insert() {
  document.getElementById("ctl00$ContentPlaceHolder1$txt").value =
  document.getElementById("ctl00$ContentPlaceHolder1$txt").value + "(__)";
  return;
  }
  //或者
  function insert() {
  document.getElementById("ctl00_ContentPlaceHolder1_txt").value =
  document.getElementById("ctl00_ContentPlaceHolder1_txt").value + "(__)";
  return;
  }好了,问题解决了,不过想想有什么更好的办法呢?到底为什么呢?其实分析一下,它是后来生成的客户端id,我们可以用C#语句Control的ClientID属性,像这样写:txt.ClientID; txt还是原来控件的id,后面的ClientID就是新生成的id。txt.ClientID是从程序里取到的后来生成新的id,这样不是更好吗。修改代码如下:
  function insert() {
  document.getElementById("<%=txt.ClientID %>").value =
  document.getElementById("<%=txt.ClientID %>").value + "(__)";
  return;
  }还有在后台Request.Form["txt"]键值需要改变,必须变为Request.Form["<%=txt.ClientID %>"]才能接收到页面的值。想想如果想要得到ID的control是一个用户控件的话,当生成页面后尽管能得到其ClientID,但是却得不到这个对象,所以也就不能设置或获得其属性了。比如,我要做的这个用户控件,由三个DropDownList组成,可是我却想得到一个完整的日期值(指在客户端),一种思路是先获得三个DropDownList的ClientID,然后再由ID1.value+ID2.value+ID3.value取得,可是如果你一个页面上需要放多个这样的用户控件的话,你需要取得多少个ClientID?显然这样做的话,工作量会很大,而且要操作众多的对象,很容易出错。
  四、总结
  这一类问题我像在我们编写程序时往往经常会遇到,总结一下:这应该属于“使用了MasterPage,或者GridView中的模版列后所有元素ID不一致问题”。由于种种原因(比如使用了MasterPage,或者GridView中的模版列),一个控件在设计时的ID往往不同于生成页面后的ID,为了获得控件客户端ID,我们可以从生成的页面入手,取控件id修改方法:
  document.getElementById("ctl00$编辑区ID$控件ID");
  document.getElementById("ctl00_编辑区ID_控件ID");

  document.getElementById("<%=控件名ID.ClientID%>"); //推荐在我们设计时往往就会出现一些莫名其妙的问题,我想我们遇到问题时,冷静思考,把握主次,从底层框架入手,纠其原因,相信最终会找到答案。



本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2011/05/07/2039932.html,如需转载请自行联系原作者

目录
相关文章
|
安全 网络协议
端口扫描神器:御剑 保姆级教程(附链接)
端口扫描神器:御剑 保姆级教程(附链接)
|
自然语言处理 API iOS开发
IDEA 优质 插件 Translation 跟随 IDEA 2022.3 版 更新翻译引擎啦
IDEA 优质 插件 Translation 跟随 IDEA 2022.3 版 更新翻译引擎啦
3645 1
|
安全 前端开发 Android开发
移动应用开发的未来:跨平台框架与原生系统之争
【4月更文挑战第26天】随着移动互联网的飞速发展,移动应用(App)成为日常生活和工作不可或缺的组成部分。本文将探讨当前移动应用开发的两大趋势——跨平台应用框架与原生操作系统应用的开发。通过分析两者的优势与局限,预测未来移动应用开发的可能方向,并讨论各自在安全性、性能和用户体验方面的影响。
|
12月前
|
人工智能 监控 5G
5G 网络切片的动态管理:实现灵活高效的网络资源分配
5G 网络切片的动态管理:实现灵活高效的网络资源分配
499 1
|
弹性计算 缓存 前端开发
阿里云服务器配置选择指南2核4G、4核8G和8核16G性能全解析!
阿里云2核4G、4核8G与8核16G服务器配置解析及选择指南。根据不同业务需求,推荐ECS经济型e、通用算力型u1、计算型c7/c8i实例。企业用户专享2核4G ECS u1实例仅199元/年,自带5M带宽;4核8G u1实例起价955.58元/年;8核16G c7实例起价6544元/年。各实例CPU性能各异,如c7采用第三代Intel Xeon处理器,适配高性能计算场景。
725 10
|
机器学习/深度学习 算法 Python
特征工程:机器学习成功的关键步骤
【6月更文挑战第4天】特征工程是机器学习的关键,涉及特征选择、构建和变换,旨在提升模型性能。通过处理原始数据,如顾客购买行为,选择相关特征,创建新特征并转换数据(如对数变换),可以增强模型预测能力。例如,对异常值丰富的收入数据进行对数变换,可提升模型稳定性和准确性。特征工程是耗时且需要创造力的过程,是连接数据与智能的桥梁,在机器学习中发挥着至关重要的作用。
194 2
|
API
uniapp使用u-search以及相关api
uniapp使用u-search以及相关api
895 1
|
前端开发 JavaScript Java
基于springboot的通知反馈系统
该系统创作于2022年4月,包含详细数据库设计。基于springboot技术,数据层为MyBatis,mysql数据库,页面使用html,具有完整的业务逻辑,适合选题:通知、消息通知、通知反馈、部门信息收集等。
基于springboot的通知反馈系统
|
C++
C++赋值函数详解
赋值函数        每个类只有一个赋值函数          由于并非所有的对象都会使用拷贝构造函数和赋值函数,程序员可能对这两个函数有些轻视。    1,如果不主动编写拷贝构造函数和赋值函数,编译器将以“位拷贝”的方式自动生成缺省的函数。
1023 0