母版页中对控件ID的处理

注:此系列记录在我实际开发中遇到的问题和收藏一些技巧文章。

本篇技巧和诀窍记录的是:母版页中对控件ID的处理。

一、问题提出

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

二、 抽象模型

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

<head id="Head1" 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>

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

<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代码:单一页面:

<form name="form1" method="post" action="Default.aspx" id="form1">
    <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="客户端插入(_)" />
</form>

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

<form name="aspnetForm" method="post" action="Default2.aspx" id="aspnetForm">
    <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="客户端插入(_)" />
</form>

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

这下知道了,难怪提示“‘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("<%=txt.ClientID %>").value =
    document.getElementById("<%=txt.ClientID %>").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("<%=控件名ID.ClientID%>"); //推荐

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

版权声明:本文为博主http://www.zuiniusn.com 原创文章,未经博主允许不得转载。

时间: 2024-12-30 03:07:25

母版页中对控件ID的处理的相关文章

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

一.问题提出 由于总体排版和设计的需要,我们往往创建母版页来实现整个网站的统一性,最近我由于统一性的需要,把原来整个项目单独的页面全部套用了母版页.但是出现了一系列失效错误. 二. 抽象模型 由于整个页面内容过多,所以我把这个页面中最为本质的问题抽象出来.原来单一页面,就是利用按钮触发JS事件,在文本域中插入“(_)”功能,其实现代码如下: <head id="Head1" runat="server"> <title>单一页面抽象模型-YJ

js获取页面容器中的控件id方法即遇到的问题

在实际开发过程中,我们会把一些控件放在容器中,这样生成出来的页面上容器中的控件id就会自动生成前缀+控件id,如果不注意就会导致js获取的时候出现错误. 通过网上查到的资料可以用document.getElementById("<%=btn.ClientID %>")来动态的获取容器中变动的控件id(btn是本来控件的id,btn.ClientID是变化之后的控件id). 但是如果把该代码放在<head runat="server">中执行,

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

原本想给一个button添加一个confirm,不同的分数提示不同的信息(大于80合格,小于80不合格,提示是否提交),最开始用了button.Atribute.Add();但是它每次获取到的是label控件在刷新前的值,后来在网上看到了ViewState[]的使用,但是还是不行,没办法,只能用js: <script> function myconfirm() { if(document.getElementById('lbl').value>=80) {return confirm('

asp.net js获取控件ID

以文本框为例: 一.未使用母版页 js可以使用document.getElementById('控件的ID')形式,也可以使用document.getElementById('<%=控件的ID.ClientID %>')的形式,代码如下: 1 <head runat="server"> 2 <title></title> 3 <script type="text/javascript"> 4 functio

MFC中给控件添加变量,DoDataExchange中

DoDataExchange函数其实是一项数据动态绑定技术.比如你在写动态按钮过程中须对按钮添加变量时,怎么添加?控件类已经写好了,其变量是已经固定的.你要添加新的变量就要用到DoDataExchange函数. 你要在对话框的构造函数里面初始化一个变量,再用DoDataExchange函数将它绑定到你的动态按扭中,比如:DDX_Check(pDX, IDC_CHECK1, m_Lesson1);这就是将m_Lesson1(这是一个外部变量,其定义在对话框的构造函数里)绑定到IDC_CHECK1中

monkeyrunner之坐标或控件ID获取方法-续

在之前的文章中,介绍过控件坐标和ID的获取方法,这里,我们再介绍一个新的工具-uiautomatorviewer. Uiautomatorviewer是Android sdk自带的工具,位置在sdk/tools下. 工具打开方法: 1.sdk/tools下,找到uiautomatorviewer,双击打开 2.在cmd命令行,直接输入uiautomatorviewer,打开该工具 打开该工具后,我们就可以开始使用了. 运行环境:Windows 使用方法: 1.连接模拟器或真机(我们这里使用模拟器

设定当前视图中所有控件字体的方法

     本范例实现的是对界面中所有的控件一次性的设置字体样式.思路是找到父控件,然后遍历子控件.如果子控件是可以修改文字的控件,那么就设置文字.这用到了控件的继承,很多控件都是继承与textview的,所以将控件均转为textview,最后设置字体即可. 布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.

android include中的控件调用

项目中经常会有一些布局是重用的,但是如何来更好的利用这些布局中的控件 转: http://zhidao.baidu.com/link?url=GU93U8Wu31dfp7mKEx52hMJkxjFLCq3WGkvZ8IMrahQT3wgAbC1Y93sKQ36_GQo3V4-Q9KWRHD6RIxMgBYj0zY7YsYNQuGFGjahZsFnz9wq <include android:id="@+id/view_counter_buttons_1" layout="

页面JS获取不到控件ID

为了使页面更加的友好,我们不可避免的要在页面上使用JS,所以在页面上使用javascript获取控件ID是很常见的事情.但是最近在使用JS的使用,遇到了一件让我很头疼的事情,在获取控件ID时,抱错了,监控显示,获取不到控件ID. 源代码: <script type="text/javascript"> Function(){ var args = window.dialogArguments; var serverTaskInfo = $("#hidTaskInf