当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > ASP.NET 2.0 创建母版页引来的麻烦

ASP.NET
ASP.NET开发:简化应用程序的开发支持Web标准
asp.net XMLHttpRequest实现用户注册前的验证
asp.net 页面间传值方法小结
asp.net url重写浅谈
asp.net 验证码生成和刷新及验证
C#精髓 GridView72大绝技 学习gridview的朋友必看
实例说明asp.net中的简单角色权限控制
asp.net网站开发包wq.dll打包下载
js与ASP.NET 中文乱码问题
asp.net checkbox 动态绑定id GridView删除提示
asp.net TextBox回车触发事件 图片在img显示
asp.net 脏字典过滤问题 用正则表达式来过滤脏数据
asp.NET 脏字过滤算法
asp.NET 脏字过滤算法 修改版
asp.net sql 数据库处理函数命令
asp.net Javascript 的几种写法与提示
ASP.NET MVC学习笔记
asp.net 中国身份证号码验证代码 非正则
Asp.net中使用Sqlite数据库的方法
asp.net 中文字符串提交乱码的解决方法

ASP.NET 2.0 创建母版页引来的麻烦


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 116 ::
收藏到网摘: n/a

  本文将为大家介绍一下 ASP.NET 2.0 在创建母版页时引来的麻烦,并分析了问题产生的实质,大家在实际操作中多多注意一下。

  一、问题提出

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

  二、 抽象模型

  由于整个页面内容过多,所以我把这个页面中最为本质的问题抽象出来。

  原来单一页面,就是利用按钮触发JS事件,在文本域中插入“(_)”功能,其实现代码如下:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head 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>

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

<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" Title="使用母版页面抽象模型-YJingLee" %>
<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代码:

  单一页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><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 name="form1" method="post" action="Default.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTEzMjE5NDA0NWRkKlEH1jSXJkIbnUaP2d9Dra8LQEk=" />
</div>
    <div>
        <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="客户端插入(_)" /></div>
<div>
    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBALVid/5DQKShrDCCQL5w9POBQL5w4vOBZPGqxUU/yvoKTqG8k+uG8YroGTv" />
</div></form>
</body>
</html>

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>使用母版页面抽象模型-YJingLee</title></head>
<body>
    <form name="aspnetForm" method="post" action="Default2.aspx" id="aspnetForm">
      <div>
        <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTEwMTY2NjE0OWRkADUETiohcorj2qXOE9M1qhFVw20=" />
     </div>
   <div>        
<script language="javascript" type="text/javascript">
// <!CDATA[
function insert() {
           document.getElementById("txt").value=document.getElementById("txt").value+"(__)";
        return;
}
// ]]>
</script>
    <div>
        <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="客户端插入(_)" /></div>
    </div>    
<div>
    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBAKyga4JAtO59ZELApOT2tEDApOTwvAC83bfMO00kt0PYcRte7XQOsXBcFE=" />
</div></form>
</body>
</html>

  是不是看到问题了,源文件控件元素的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("").value=document.getElementById("").value+"(__)";
  return;
  }

  还有在后台Request.Form["txt"]键值需要改变,必须变为Request.Form[""]才能接收到页面的值。想想如果想要得到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("");

  至于为什么,是自己还没有深刻理解其中的根源还是.NET机制问题呢?

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