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

ASP.NET
使用函数传递参数来执行相应的数据库操作
如何实现在窗体和窗体之间进行传递数据
ASP.NET中文显示之两种解决方法
ASP.NET、JSP及PHP之间的抉择
ASP.NET 2.0发送电子邮件中存在的问题
谈谈HtmlControl与WebControl的区别与用途
从ASP.NET 1.1升级到ASP.NET 2.0要考虑的Cookie问题
通过系统配置来提高ASP.NET应用程序的稳定性
妙用ASP2.0中的URL映射改变网址
AJAX实现web页面中级联菜单的设计
ASP.NET跨页面传值技巧总结
再议ASP.NET DataGrid控件中的“添加新行”功能
Geometry 对象浅析
重构CollapsibleSplitter
如何利用.NET Framework使用RSS feed
ASP.NET获取IP与MAC地址的方法
在ASP.NET 2.0中使用样式、主题和皮肤
ASP.NET中为GridView添加删除提示框
ASP.NET 2.0,无刷新页面新境界
看看一个.net版对话框控件

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 90 ::
收藏到网摘: 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机制问题呢?

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