程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> ASP.NET 2.0 創建母版頁引來的麻煩

ASP.NET 2.0 創建母版頁引來的麻煩

編輯:關於.NET

本文將為大家介紹一下 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機制問題呢?

  在我們設計時往往就會出現一些莫名其妙的問題,我想我們遇到問題時,冷靜思考,把握主次,從底層框架入手,糾其原因,相信最終會找到答案。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved