一、问题提出

由于总体排版和设计的需要,我们往往创建母版页来实现整个网站的统一性,最近我由于统一性的需要,把原来整个项目单独的页面全部套用了母版页。但是出现了一个错误……在我的Blog中记录一下,方便大家参考。

二、 抽象模型

由于整个页面内容过多,所以我把这个页面中最为本质的问题抽象出来。原来单一页面,就是利用按钮触发JS事件,在文本域中插入“(_)”功能,其实现代码如下:

  1. <head id="Head1" runat="server">
  2. <title>单一页面抽象模型-YJingLee</title>
  3. <script language="javascript" type="text/javascript">
  4. // <!CDATA[
  5. function insert() {
  6. document.getElementById("txt").value=document.getElementById("txt").value+"(__)";
  7. return;
  8. }
  9. // ]]>
  10. </script>
  11. </head>
  12. <body>
  13. <form id="form1" runat="server">
  14. <div>
  15. <textarea id="txt" runat="server" name="txt" rows="10" cols="50"></textarea>
  16. <asp:Button ID="btnInsert" runat="server" Text="服务器端插入(_)" OnClientClick="insert();" />
  17. <input id="btnInsert2" name="insert" onclick="insert();" type="button" value="客户端插入(_)"
  18. runat="server" /></div>
  19. </form>
  20. </body>
  21. </html>


上述页面可以正常使用。后来使用模板页后,其代码如下:

  1. <asp:content id="Content1" contentplaceholderid="ContentPlaceHolder1" runat="Server">
  2. <script language="javascript" type="text/javascript">
  3. // <!CDATA[
  4. function insert() {
  5. document.getElementById("txt").value = document.getElementById("txt").value + "(__)";
  6. return;
  7. }
  8. // ]]>
  9. </script>
  10. <div>
  11. <textarea id="txt" runat="server" name="txt" rows="10" cols="50"></textarea>
  12. <asp:Button ID="btnInsert" runat="server" Text="服务器端插入(_)"  OnClientClick="insert();"/>
  13. <input id="btnInsert2" name="insert" onclick="insert();" type="button"
  14. value="客户端插入(_)" runat="server"/></div>
  15. </asp:content>

复制代码

当打开后按下按钮出现了“Microsoft JScript 运行时错误: 'document.getElementById(...)' 为空或不是对象”。这是什么原因呢?原来好好的,怎么套用个母版页就出现这个奇怪的问题呢?困扰了好久,和朋友讨论了一下,终于找到了答案……

三、分析本质

原来我们仔细看看其生成的HTML代码:单一页面:

  1. <form name="form1" method="post" action="Default.aspx" id="form1">
  2. <textarea name="txt" id="txt" rows="10" cols="50"></textarea>
  3. <input type="submit" name="btnInsert" value="服务器端插入(_)" onclick="insert();" id="btnInsert" />
  4. <input name="btnInsert2" type="button" id="btnInsert2" onclick="insert();" value="客户端插入(_)" />
  5. </form>


再看看套用母版页之后,生成的HTML代码:

  1. <form name="aspnetForm" method="post" action="Default2.aspx" id="aspnetForm">
  2. <textarea name="ctl00$ContentPlaceHolder1$txt" id="ctl00_ContentPlaceHolder1_txt"
  3. rows="10" cols="50"></textarea>
  4. <input type="submit" name="ctl00$ContentPlaceHolder1$btnInsert" value="服务器端插入(_)"
  5. onclick="insert();" id="ctl00_ContentPlaceHolder1_btnInsert" />
  6. <input name="ctl00$ContentPlaceHolder1$btnInsert2" type="button" id="ctl00_ContentPlaceHolder1_btnInsert2"
  7. onclick="insert();" value="客户端插入(_)" />
  8. </form>


是不是看到问题了,源文件控件元素的ID和生成HTML文件的ID不一致。表单from的name属性和id属性变成了aspnetForm,控件的id属性被无缘无故了加上了ctl00_ContentPlaceHolder1_前缀,其name属性也加上了 ctl00$ContentPlaceHolder1$前缀。

这下知道了,难怪提示“'document.getElementById(...)' 为空或不是对象”的错误了,原来生成页面后其ID都变了。那么我们如何解决它呢?既然他id变了,我们就把JS代码id改为生成后的id。代码如下:

  1. function insert() {
  2. document.getElementById("ctl00$ContentPlaceHolder1$txt").value =
  3. document.getElementById("ctl00$ContentPlaceHolder1$txt").value + "(__)";
  4. return;
  5. }
  6. //或者
  7. function insert() {
  8. document.getElementById("ctl00_ContentPlaceHolder1_txt").value =
  9. document.getElementById("ctl00_ContentPlaceHolder1_txt").value + "(__)";
  10. return;
  11. }


好了,问题解决了,不过想想有什么更好的办法呢?到底为什么呢?其实分析一下,它是后来生成的客户端id,我们可以用C#语句Control的 ClientID属性,像这样写:txt.ClientID; txt还是原来控件的id,后面的ClientID就是新生成的id。txt.ClientID是从程序里取到的后来生成新的id,这样不是更好吗。修改代码如下:

  1. function insert() {
  2. document.getElementById("<%=txt.ClientID %>").value =
  3. document.getElementById("<%=txt.ClientID %>").value + "(__)";
  4. return;
  5. }


还有在后台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修改方法:

  1. document.getElementById("ctl00$编辑区ID$控件ID");
  2. document.getElementById("ctl00_编辑区ID_控件ID");
  3. document.getElementById("<%=控件名ID.ClientID%>"); //推荐


在我们设计时往往就会出现一些莫名其妙的问题,我想我们遇到问题时,冷静思考,把握主次,从底层框架入手,纠其原因,相信最终会找到答案。

来源:http://club.topsage.com/thread-480447-1-1.html

[转]ASP.NET母版页中对控件ID的处理的更多相关文章

  1. Asp.Net 之 母版页中对控件ID的处理

    一.问题提出 由于总体排版和设计的需要,我们往往创建母版页来实现整个网站的统一性,最近我由于统一性的需要,把原来整个项目单独的页面全部套用了母版页.但是出现了一系列失效错误. 二. 抽象模型 由于整个 ...

  2. 041. asp.net中内容页访问母版页中的控件

    母版页运行机制: 用户通过输入内容也的URL来请求某个页面, 获取该页面后, 读取@Page指令, 如果该指令引用了一个母版页, 则也读取该母版页, 如果也是第一次请求这两个页面, 则母版页和被请求的 ...

  3. 母版页中ContentPlaceHolder 控件的作用

    文章转自  http://wenku.baidu.com/link?url=7sLN0ihgZQ1XfX47b_y8qbpIVjS5T75Q1xvaoyIQ6OiKIgvzyVyRccnU9e9fqo ...

  4. 母版页改变被嵌套的页面中的控件ID的解决方法

    使用过模板页的朋友都会很纳闷,怎么页面的用js通过getElementById(“id”):找不到对象.查看了页面源代码才发现,原来控件的ID变了,这是母版页导致的.因为母版页怕母版页本身页面中的控件 ...

  5. 向asp.net项目中添加控件AspNetPager

    1.打开项目,把.dll文件放入项目中: 2.在工具栏中添加一个自定义选项卡

  6. [转载]ASP.NET中TextBox控件设立ReadOnly="true"后台取不到值

    原文地址:http://www.cnblogs.com/yxyht/archive/2013/03/02/2939883.html ASP.NET中TextBox控件设置ReadOnly=" ...

  7. asp.net中验证控件的使用方法

    用于检查是否有输入值 :RequiredFieldValidator(必须字段验证) 按设定比较两个输入 :CompareValidator(比较验证) 输入是否在指定范围 :RangeValidat ...

  8. ASP.NET 后台不识别ASPX中的控件

    请问后台不识别ASPX中的控件,怎么解决 这个程序是在网上下载的 C# code <asp:DataGrid runat="server" ID="dgList1& ...

  9. ASP.NET在母版页或内容页上获取控件ID

    原本想给一个button添加一个confirm,不同的分数提示不同的信息(大于80合格,小于80不合格,提示是否提交),最开始用了button.Atribute.Add();但是它每次获取到的是lab ...

随机推荐

  1. 一:Redis安装

    redis在Linux上的安装 1)安装redis编译的c环境,yum install gcc-c++ 2)将redis-2.6.16.tar.gz上传到Linux系统中 3)解压到/usr/loca ...

  2. MySQL prompt命令

    修改提示符,设置后挺方便的 例如: 几个好用的参数 \d 当前数据库 \u 当前用户 \h 当前主机 更多参数可以参考mysol官方文档 参考文档:https://dev.mysql.com/doc/ ...

  3. 单例模式的c++实现

    #pragma once #include <iostream> #include <memory> #include <Windows.h> using name ...

  4. Angular-ui/bootstarp modal 主控制器与模态框控制器传值

    调用模态框: $scope.open = function (size) { //这里很关键,是打开模态框的过程 var modalInstance = $uibModal.open({ animat ...

  5. css设置一行显示,超出部分显示...

    碰到一些介绍时候需要一行显示,然后超出部分用...替代 white-space: nowrap;不换行显示text-overflow: ellipsis;以...显示overflow: hidden; ...

  6. 欣欣的留言板项目====超级触动的dbUtil实现留言板

    留言板管理系统 我的完成效果图: 提交后: 我的留言板基本架构如图: 创建留言板数据库: 刚开始我的前台主页中写留言信息表单: <body> <h1>留言板</h1> ...

  7. MASQL语法大全

    mysql sql语句大全 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql se ...

  8. <Android 应用 之路> 百度地图API使用(3)

    前言 上一篇讲解并实践了百度地图基本显示,地图类型,实时交通图,热力图,地图控制和手势控制,今天看下在地图上添加view和覆盖物. 地图Logo不允许遮挡,可通过mBaiduMap.setPaddin ...

  9. awk获取外部变量

    语法 awk [ -F re] [parameter...] ['pattern {action}' ] [-f progfile][in_file...] 获得普通外部变量 [xingxing.dx ...

  10. listview cacheColorHint,listSelector属性

    ListView是常用的显示控件,默认背景是和系统窗口一样的透明色,如果给ListView加上背景图片,或者背景颜色时,滚动时listView会黑掉, 原因是,滚动时,列表里面的view重绘时,用的依 ...