Go homepage(回首页)
Upload pictures (上传图片)
Write articles (发文字帖)

The author:(作者)delv
published in(发表于) 1/27/2014 6:46:34 AM
ASP.NET,2.0,创建母版页引来的麻烦_[Asp.Net教程]

ASP.NET 2.0 创建母版页引来的麻烦_[Asp.Net教程]

















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




  一、问题提出




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




  二、 抽象模型




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




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
















以下是引用片段:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>



单一页面抽象模型-YJingLee







onclick="insert();" type="button" value="客户端插入(_)" runat="server"/>



  




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
















以下是引用片段:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" Title="使用母版页面抽象模型-YJingLee" %>





onclick="insert();" type="button" value="客户端插入(_)" runat="server"/>

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




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




  三、分析本质




  原来我们仔细看看其生成的HTML代码:




  单一页面:
















以下是引用片段:


单一页面抽象模型-YJingLee









onclick="insert();" id="btnInsert" />
onclick="insert();" value="客户端插入(_)" />








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
















以下是引用片段:


使用母版页面抽象模型-YJingLee









onclick="insert();" id="ctl00_ContentPlaceHolder1_btnInsert" />
onclick="insert();" value="客户端插入(_)" />









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




  这下知道了,难怪提示“'document.getElementById(...)' 为空或不是对象”的错误了,原来生成页面后其ID都变了。




  那么我们如何解决它呢?既然他id变了,我们就把JS代码id改为生成后的id。代码如下:
















以下是引用片段:
  function insert() {
  document.getElementById("ctl00ContentPlaceHolder1txt").value=document.getElementById("ctl00ContentPlaceHolder1txt").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["<%=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("");




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




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




作者: YJingLee'Blog 出处: 博客园


























If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)




QQ:154298438
QQ:417480759