首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包

宁波.net俱乐部 [加入]

推进.net在宁波及周边地区的推广,不定期举行新技术推广会和.net方向的交流会,欢迎宁波地区的.net爱好者加入
客户端如何获取服务器控件的值
发表时间:2008-03-21 10:42:06   楼主:edisundong

1.概括

这个问题宁波.net俱乐部里多次有人提起,故发在这里。

简单的将一句话document.getElementById("服务器端控件的ClientID属性").value 获取value

 

 

2.实例

比如 有一个名为TextBox1的TextBox,在js里访问就是document.getElementById("<%=TextBox1.ClientID%>").属性

实例代码如下:

 

    <script type="text/javascript">
    function getText()
    {
       alert(document.getElementById('<%=TextBox1.ClientID%>').value);
    }
    </script>

    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <input type="button" onclick="getText()" value="取值" />

实例完毕

 

3.原理

 (续)

4.高级

 (续)





 
发表时间:2008-03-21 10:47:21 1 楼:pciak
偷学一招
发表时间:2008-03-21 10:49:26 2 楼:int08h

来个更变态的方法,把Server Control的ID都改回去,不用NamingContainer

 

在Global.asax的Application_BeginRequest方法中遍历所有的控件,如果控件ID里带有$符号的,就把他变回去,具体代码

 

void Application_BeginRequest(object sender, EventArgs e)
{
    var form = HttpContext.Current.Request.Form;
    //先把IsReadOnly改成false
    form.GetType()
        .GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic)
        .SetValue(form, false, null);

    foreach (var key in form.AllKeys.Where(key => key.Contains("$")))
    {
        var value = form[key];
        form.Remove(key);
        var newKey = key.Substring(key.LastIndexOf("$") + 1);
        form.Add(newKey, value);
    }
}
效率极低,但很好玩,所以随便发发了
发表时间:2008-03-21 10:53:41 3 楼:spring21st

js检测不出来控件的名称,比如Textbox id= txtName,查看源文件时它其实就变成了ctl00$ContentPlaceHolder1$txtName ,将

js中的txtName换成ctl00$ContentPlaceHolder1$txtName 也是可以实现的。就是麻烦点

发表时间:2008-03-21 14:08:55 4 楼:int08h

1.为什么ID会变

ASP.NET的服务器控件ID会在生成HTML时变化,这使得许多人都摸不着头脑。当然如果保持原有的ID也可以正常工作的话,MS也不会空到搞出这个这么复杂的名堂,所以我们就看看为什么服务器控件的ID“必须”变化吧

始作俑者――Master page, Template control

ASP.NET中,为了消除使用iframe制作框架的难维护性等缺点,MS引入了被称为母页板(Master page)的机制,在母页中使用ContentPlaceHolder控件来存放子页的内容,其原理看似相当简单――将aspx文件自上而下进行解释,遇到ContentPlaceHolder时递归解释子页面内容

然而正是这看似强大又简单的功能之下,隐藏了命名重复的危机,试想我们在母页和子页中分别命名了IDMyLabel的控件,并且控件的ID保持不变。那么在输出的HTML页面中也会出现2ID相同的元素,使得最终页面无法符合规范

同样的,对于Wizard等模板控制,因为可以在其内加入多个模板,也会导致命名冲突的问题,试想Repeater控件最终生成了数十个相同ID的控件的场景,是不是觉得背后发毛呢?

2.MS的方案――NamingContainer

为了解决命名冲突的问题,MS创造性地提出了NamingContainer的理念,使得不同层次的控件拥有完全不同的ID

对于NamingContainer的解释并不复杂,试着看一下某aspx页面的控件树

Master—Default—MyLabel

当使用NamingContainer规则生成MyLabel的客户端ID的时候,会查看其上一级命名提供者,随后将上一级的ClientID取来与自己的ID进行拼接,大致思路如下

string clientID = ID;

If (NamingContainer != null) {

clientID = NamingContainer.ClientID + “_” + clientID;

}

当然如果NamingContainer本身还有上一级的命名提供的话,会进行递归调用

3.演示

为了更形象地解释此命名规范,可以制作一个简单地例子

首先建立一个母页,命为Site.master,随后建立Default.aspx并应用Site.master,在Default.aspx中放置一名为MyLabelLabel控件,在此我们使用代码显示MyLabelID, ClientIDUniqueID,并显示出其NamingContainerID

<asp:Content ID="DefaultBody" ContentPlaceHolderID="SiteBody" runat="server">        <asp:Label ID="MyLabel" runat="server">简单命名</asp:Label>        <div style="width: 200px; float: left">            ID</div>        <div>            <%= MyLabel.ID %></div>        <div style="width: 200px; float: left">            UniqueID</div>        <div>            <%= MyLabel.UniqueID %></div>        <div style="width: 200px; float: left">            ClientID</div>        <div>            <%= MyLabel.ClientID %></div>        <div style="width: 200px; float: left">            NamingContainer</div>        <div>            <%= MyLabel.NamingContainer.ID %></div></asp:Content>

运行结果如下:

简单命名 ID    MyLabelUniqueID    ctl00$SiteBody$MyLabelClientID    ctl00_SiteBody_MyLabelNamingContainer    SiteBody 其中UniqueIDClientID相似,但以$作为分隔符,此属性作为服务器端对控件的唯一标识 对于带有模板的控件效果也是如此,在此我们以Wizard控件作为测试对象,aspx代码如下<asp:Content ID="DefaultBody" ContentPlaceHolderID="SiteBody" runat="server">        <asp:Wizard ID="MyWizard" runat="server" DisplaySideBar="false">            <WizardSteps>                <asp:WizardStep ID="MyWizardStep" runat="server">                    <asp:Label ID="YourLabel" runat="server">模板控件命名</asp:Label>                    <div style="width: 200px; float: left">                        ID</div>                    <div>                        <%= YourLabel.ID%></div>                    <div style="width: 200px; float: left">                        UniqueID</div>                    <div>                        <%= YourLabel.UniqueID%></div>                    <div style="width: 200px; float: left">                        ClientID</div>                    <div>                        <%= YourLabel.ClientID%></div>                    <div style="width: 200px; float: left">                        NamingContainer</div>                    <div>                        <%= YourLabel.NamingContainer.ID%></div>                </asp:WizardStep>            </WizardSteps>        </asp:Wizard></asp:Content> 

运行结果如下

模板控件命名 ID    YourLabelUniqueID    ctl00$SiteBody$MyWizard$YourLabelClientID    ctl00_SiteBody_MyWizard_YourLabelNamingContainer    MyWizard 

注意到此处YourLabelNamingContainer变为了MyWizard,且UniqueIDClientID中都增加了MyWizard字样

 

4.关于NamingContainer

并不是所有的控件都有NamingContainer功能,在ASP.NET中,控件继承关系如下

Control—TemplateControl—UserControl

Control—WebControl

在这两条线中,只有TemplateControl及其子实现了INamingContainer接口,所以像LabelWebControl是没有NamingContainer功能的(当然他们也不会有子控件)

事实上,要实现NamingContainer功能非常简单,只需要简单地为控件加上INamingContainer接口即可,此接口并没有定义任何方法,所以对于类是没有负担的

 

说得很乱,呵呵,见笑了

发表时间:2008-03-21 15:07:47 5 楼:pciak
 前,当我们需要在脚本里访问页面内一个对象的时候,一般都是通过对象的 id 或 name。就像这样——
 !--Test.html-->
 / ...
 unction getText()
 
  return document.form1.Text1.value; // Text1就是对象的 id
 

 / ...

 INPUT id="Text1" type="text" ...>

 在,ASP.NET 让我们越来越习惯使用 TextBox 作为用户输入的途径。如果我们想在客户端脚本里访问一个 TextBox,原先的做法就行不通了——
 !--Test.aspx-->
 / ...
 unction getText()
 
  return document.form1.Text1.value; // Text1还是对象的 id?
 

 / ...

 asp:TextBox id="Text1" .../>

 览页面时,会有一个脚本错误——“Text1对象不存在”。原因就在于,Text1作为服务器端控件 TextBox,在被发送到客户端之前,先由.NET Framework 进行转换,而它的id显然也是转换的一部分。如果你在客户端查看页面的源代码,你可以发现原先的 Text1已经不存在,取而代之的是一个普通的 INPUT——
 input name="Test:Text1" type="text" id="Test_Text1" />

 就是转换的结果,id 不再是设计时所指定的 id。如果我们要在客户端访问这个文本输入框,也必须改变访问的 id。如何改变?直接将
 ocument.form1.Text1
 为
 ocument.form1.item("Test_Text1" // 保险起见,使用 item 由 id 或 name 得到控件
 者
 ocument.getElementByID("Test_Text1" // 保险起见,使用 getElementByID 由 id 或 name 得到控件

 以吗?当然可以!只要你的控件 id 固定是"Text1"。
 是,只有这个条件还不够。"Test"又是什么?它也应该被考虑在内(幸好 form 的 id 不会改变,否则要关心的内容又会多一个)。
 或许已经看出,Test 就是这个 Web 页面的名字。对吗?——不完全对
 切地说,控件转换后 id 中的"Test"是其所在的 Web 窗体对象的 ClientID。所有的 ASP.NET 对象都在服务器端有一个实例(如果你面向对象的基础不够,建议也补完一次吧),而这个"Test",就是这个页面实例对象的 ClientID。而 ClientID,则是每个 Web 窗体页的一个属性,它指明了这个Web窗体在客户端的标识。
 什么要这么复杂?道理很简单,我们并不能在客户端脚本里确定页面的 ClientID 和控件的 ID。
 应该怎样做呢?
 在服务器端代码里生成客户端 JavaScript。”——似乎非常复杂,其实并不困难,只要在服务器端 Page_Load 事件里加上(在 IsPostBack 判断之外)——
 egisterStartupScript("start",
  "\n<script>\n" +
  "function getText()\n" +
  "{\n" +
  " return document.forms(0).item('" + this.ClientID + ":" + this.Text1.ID + "');\n" +
  "}\n" +
  "</script>\n";

 egisterStartupScript 是 Web 窗体(System.Web.UI.Page 类)的一个方法,作用是在生成的页面里注册客户端脚本。
 这里,我们添加了一个 getText()函数,作用和之前的 getText()一样,所不同的在于,它所访问的控件 id并非脚本内指定,而是在服务器端根据页面的 ClientID(this.ClientID,this就是页面自己)和 Text1控件的 ID(this.Text1.ID)动态生成的。
编译之后重新浏览,我们会在新的页面源代码里找到这个由服务器端代码生成的 JavaScript 函数。此时,在页面的其他地方调用 getText()函数就将正确得到 Text1中的内容了。

【相关链接】: http://www.evget.com/zh-CN/article/2579/default.aspx (本网站不保证链接的安全性)
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|版权声明|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo