ASP.NET 3.5控件和组件开发技术之客户端回发/回调揭密
本文摘录自《纵向切入ASP.NET 3.5控件和组件开发技术》。
对于服务端控件元素,比如ASP.NET的Button标准服务端控件在提交时可以自动把请求发送到服务端处理,这样的控件我们不用自己处理它们的事件回发;但对于呈现不引起回发的HTML元素,如“文本框”(TextBox)或“链接按钮”(LinkButton),而希望由控件启动回发,则可以在ASP.NET中通过依靠客户端脚本的事件结构进行编程来实现这一功能。
完整地处理一个事件则还需要回发和捕捉。捕捉是IPostBackEventHandler接口的事情,上一节讲得比较清楚了,这一节主要讲回发(客户端回发请求到服务端)。
下面就以一些常用的HTML标记展开分析客户端回发机制,以及各种HTML标记的回发形式。
5.2.2.1 设置HTML Button标记的类型为submit
如上节的PostBackEventControl控件例子就是采用设置HTML Button标记的类型为submit的方式从客户端提交回发的。回发代码如下:
output.Write("<INPUT TYPE=submit name=" + this.UniqueID + " Value='单击我' />");
INPUT是标准的HTML标记控件,它默认情况下没有runat="server",并且这些控件默认情况下只能处理一些客户端方法。INPUT的TYPE属性表示该标记的控件类型,如:type=button表示按钮;type=submit表示可提交表单功能的按钮;type=text表示文本框控件;type=file表示上传文件控件等。这里主要说明的是当type=submit类型的控件表示提交按钮时,它显示的样式与type=button的效果一样,不同的是单击它后可以提交表单到服务器,且不需要另外的代码,ASP.NET默认情况下是提交表单到当前页面。type=submit提交功能是从IE 3.0版开始支持的,只要浏览器版本不小于此版本都可使用该功能。
5.2.2.2 使用方法GetPostBackEventReference 得到回发脚本
1.为HTML客户端控件增加回发功能
一般页面中的按钮并不都是type=submit类型的,大部分是type=button类型的按钮,把上面5.2.2.1节的代码段中的type=submit修改成type=button,修改后的代码如下:
output.Write("<INPUT TYPE=button name=" + this.UniqueID + " Value='[使用提交按钮]' />");
由于此代码段中的按钮的type属性由sumbit改成了一般按钮类型button,则此按钮输出后将不再具有回发到服务端的功能。为了使一般按钮也具有回发的功能,ASP.NET提供了Page.ClientScript.GetPostBackEventReference方法。ClientScript类型为ClientScriptManager,该类主要功能是在Web应用程序中定义用于管理客户端脚本的方法。GetPostBackEvent Reference方法体结构如下:
GetCallbackEventReference(String, String, String, String, String, Boolean)
此方法功能是获取一个对客户端函数的引用;调用该方法时,将启动一个对服务器事件的客户端回调。此重载方法的客户端函数包含指定的目标、参数、客户端脚本、上下文、错误处理程序和布尔值。
在期望不执行回发而从客户端运行服务器代码的情况下,可以使用ClientScriptManager类来调用客户端回调。这称为对服务器执行带外回调。在客户端回调中,客户端脚本函数向ASP.NET网页发送异步请求。网页修改其正常生命周期来处理回调。使用GetCallbackEvent Reference方法获取一个对客户端函数的引用,当调用该函数时,它将启动一个对服务器端事件的客户端回调。
使用GetCallbackEventReference方法对上面代码增加回调客户端功能,修正后的代码如下:
output.Write("<INPUT type=button name=/"{0}/" value='[使用Page.ClientScript对象方法]' onclick=/"{1}/">", this.UniqueID, Page.ClientScript.GetPostBackEvent Reference(this, ""));
Page.ClientScript.GetPostBackEventReference方法的第一个参数传递当前控件引用,在实际应用中可以传递任意控件引用,包括子控件;第二个参数为可选的命令参数,这里设置为null,一般同时处理多个按钮时可以设置该参数为不同的命令名称。
另外,Page.ClientScript对象还有个非常重要的方法GetCallbackEventReference。使用GetCallbackEventReference方法获取一个对客户端函数的引用,当调用该函数时,它将启动一个对服务器端事件的客户端回调,可以支持设置客户端回调方法名称等,在这里仅简单提一下,在后面还有专门章节介绍ASP.NET控件开发对客户端的支持。
转入正题,在代码中增加按钮的onclick单击事件,当单击按钮时会调用GetPostBackEvent Reference方法返回的一串客户端脚本,并且在页面中生成一个客户端方法和两个type=hidden的隐藏域控件。下面是以上代码呈现到客户端的HTML代码:
<INPUT type=button name="PostBackFromClientControl1"value='[使用Page. ClientScript对象方法]'onclick="__doPostBack('PostBackFromClientControl1','')">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
从上面最终输出的HTML源代码可以看到,Button控件的单击事件会执行一个名为_doPostBack的方法,并且此方法也是自动生成在页面中的。在_doPostBack方法中把事件目标对象eventTarget(调用GetPostBackEventReference方法时传递的第一个参数,为当前控件)赋值给当前Form对象,把事件参数对象eventArgument(调用GetPostBackEventReference方法时传递的第二个参数),最后调用Form对象的提交方法,提交窗体,到这里就实现了我们想要的回发功能。
还要注意到以下两句自动生成的代码:
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
这是两个隐藏域类型控件,主要用来存储事件目标对象和事件参数对象的值。还有,在以上的script标记之间,有个嵌套的//<![CDATA[ //]]> 子句,该句与纯控件开发技术无关。该句的功能是通知HTML读取器下面这段不是HTML的内容,需要按附加的转义字符分开保存,以防代码解析出错。
2.为服务端控件生成回发脚本
Page.ClientScript.GetPostBackEventReference方法还可以为服务端控件生成自己的回发脚本,可以从客户端回发。
ASP.NET标准的Button服务端控件最终生成的HTML标记无非也是生成一个type=submit类型的控件。对于服务端控件也可以设置客户端回发功能。比如在使用Button控件时把UseSubmitBehavior属性设置为false,则禁用按钮的自动提交功能,就可以使用GetPostBackEventReference方法返回Button控件的客户端回发事件脚本,代码如下所示:
string strPostBackCode =
this.Page.ClientScript.GetPostBackEventReference(button1,”edit”);
然后把Button的客户事件与生成的回发事件脚本进行关联:
this.button1.Attributes[“onclick”] = strPostBackCode;
其他服务端控件也是这样设置的。
5.2.2.3 使用方法GetPostBackClientHyperlink得到回发脚本
这种方式的原理与GetPostBackEventReference类似。该方法的功能是获取一个脚本引用,与前者有一点区别是在其开头附加一个javascript: 前缀,该前缀属于JavaScript基本语法,常用来在非脚本语言(如HTML)源代码中告诉浏览器该前缀后面的格式串作为JavaScript脚本语言来解析,如:javascript:alert(‘hello’)即表示弹出一个“hello”对话框。该引用可在客户端事件中回发到指定控件的服务器,回发时使用指定的事件参数和一个布尔值指示是否为事件验证注册该回发。方法体结构如下:
GetPostBackClientHyperlink(Control, String, Boolean)
跟GetPostBackEventReference相同,第一个参数为事件目标对象;第二个参数为可选参数;第三个参数表示是否为验证注册回发事件。
下面看一个应用示例,代码如下:
string href = Page.ClientScript.GetPostBackClientHyperlink(this, "");
output.AddAttribute(HtmlTextWriterAttribute.Href, href);
output.RenderBeginTag(HtmlTextWriterTag.A);
output.Write("[使用Page.ClientScript对象的GetPostBackClientHyperlink方法]");
output.RenderEndTag();
与前面不同,这里是输出一个HTML的<a>标签。相信读者已经猜到GetPostBackClientHyperlink的应用场景了(通过方法名***Hyperlink就能够看得出它是专为哪个控件使用的功能)。直接看一下最终生成的客户端的HTML源代码:
<a href="javascript:__doPostBack('PostBackFromClientControl1','')">[使用Page.ClientScript对象的GetPostBackClientHyperlink方法]</a>
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
从上面代码可以看到,除了这句:
href="javascript:__doPostBack('PostBackFromClientControl1','')"
链接触发方式与前面Button控件的onclick触发方式有些不同外,其他的代码完全正确一样。
另外,ASP.NET会自动处理可重用部分代码,比如当页面中有多个可提交元素时,处理页面提交的公共方法_doPostBack在当前页面中总是生成一个,不会生成冗余。
关于GetPostBackClientHyperlink方法的使用就讲这么多。本节主要讲几种常用HTML标签的调用客户端回发的方式以及客户端回发的原理。注意,使用GetPostBackEventReference方法和GetPostBackClientHyperlink方法定义客户端回发事件。这些方法启用客户端脚本函数,在调用这些函数时,它们将促使服务器向该页回发。客户端回发与客户端回调的区别在于网页处理客户端回发事件要用完一个正常的生命周期,而GetCallbackEventReference是异步请求,在客户端回调中,客户端脚本函数向ASP.NET网页发送异步请求,网页修改其正常生命周期来处理回调。两者调用是有些区别的。
ASP.NET 3.5控件和组件开发技术之客户端回发/回调揭密的更多相关文章
- 《纵向切入ASP.NET 3.5控件和组件开发技术》笔记:高效率事件集合对象
在之前讲的几个例子中,使用的是最普通的定义事件方法,比如KingTextBox中事件是这样定义的:/// <summary>/// 获得本书更多内容,请看:/// http://blog. ...
- ASP.NET关于Login控件使用,LoginView 控件,CreateUserWizard 控件
原文:ASP.NET关于Login控件使用,LoginView 控件,CreateUserWizard 控件 Login控件它是属于Membership服务的一部分,必须配置Membership提供程 ...
- 轻松学习Asp.net中的控件
C/S 结构,即大家熟知的客户机和服务器结构.它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销.目前大多数应用软件 ...
- [转载]ASP.NET中TextBox控件设立ReadOnly="true"后台取不到值
原文地址:http://www.cnblogs.com/yxyht/archive/2013/03/02/2939883.html ASP.NET中TextBox控件设置ReadOnly=" ...
- ASP.NET Web数据控件
ASP.NET Web数据控件 1.数据控件简介 这包括数据源控件和格式设置控件,前者使您可以使用 Web 控件访问数据库中的数据,后者使您可以显示和操作ASP.NET 网页上的数据. 2.数据控件 ...
- 016. asp.net的验证控件
RequiredFileldValidator: 检查某个字段是否输入; 空值检查 主要属性: ControlToValidate:要验证的控件 ErrorMessage:错误提示信息 Compare ...
- ASP.NET让FileUpload控件支持浏览自动上传功能的解决方法
ASP.NET的FileUpload控件默认是不支持服务端的onchange事件的,此时可以用一种变通的方法来实现这一功能. 这就需要借用客户端的onchange事件,调用__doPostBack方法 ...
- (九)ASP.NET自定义用户控件(2)
http://www.cnblogs.com/SkySoot/archive/2012/09/04/2670678.html 用户控件 在 .NET 里,可以通过两种方式把自己的控件插入到 Web 窗 ...
- asp.net中Repeater控件用法笔记
大家可能都对datagrid比较熟悉,但是如果在数据量大的时候,我们就得考虑使用 repeater作为我们的数据绑定控件了.Repeater控件与DataGrid (以及DataList)控件的主要区 ...
随机推荐
- 用C++实现简单随机二元四则运算
让我们想看看二元四则运算都需要实现什么: (1) 定制题目数量 (2) 是否有乘除法 (3) 题目数值范围 (4) 加减有无负数 (5) 除法有无余数 (6) 是否支持分数(真分数.假分数…) (7) ...
- 结对编程学习fault、error、failure三种状态
点滴成就 学习时间 新编写代码行数 博客量(篇) 学习知识点 第一周 10小时 0 0 了解软件工程 第二周 10小时 0 1 项目开题 第三周 15小时 0 1 开通博客.开展项目调查 第四周 20 ...
- Redis 备份数据的两种方式
既然是数据库,那就一定有数据备份方式了,而且 Redis 是内存形式的数据库,更需要数据备份了,要不然断电数据就全都丢失了. Redis 数据备份有两种方式: RDB(数据快照) AOF(记录操作日志 ...
- MySQL---索引算法B+/B-树原理(二)
B+/-Tree原理 B-Tree介绍 B-Tree是一种多路搜索树(并不是二叉的): 1.定义任意非叶子结点最多只有M个儿子:且M>2: 2.根结点的儿子数为[2, ...
- HDU4747——2013 ACM/ICPC Asia Regional Hangzhou Online
啦啦啦. 这是杭州网赛的一个题目,当时没做出来,当然这个想法确实比较难想到. 题目质量很高,这个题目也很特别,以前都没做过类似的题目.让我又一次体验了线段树的强大力量. 题目的意思是给你n个数a1-a ...
- caffe框架下目标检测——faster-rcnn实战篇问题集锦
1.问题 解决方案:没编译好,需要在lib下编译make 需要在caffe-fast-rcnn下编译make或者make all -j16 ,还需要make pycaffe 2.问题 解决方案:/p ...
- 洛谷 P4116 Qtree3
Qtree系列第三题 我是题面 读完题大概不难判断是一道树剖的题 这道题的关键是记录两种状态,以及黑点的序号(不是编号) 线段树啊当然 定义两个变量v,f,v表示距离根节点最近的黑点,默认-1,f则表 ...
- 【刷题】BZOJ 3172 [Tjoi2013]单词
Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N ...
- 【BZOJ4522】密匙破解(Pollard_rho)
[BZOJ4522]密匙破解(Pollard_rho) 题面 BZOJ 洛谷 题解 还是\(Pollard\_rho\)的模板题. 呜... #include<iostream> #inc ...
- Hbase(一)基础知识
一.Hbase数据库介绍 1.简介 HBase 是 BigTable 的开源 java 版本.是建立在 HDFS 之上,提供高可靠性.高性能.列存储. 可伸缩.实时读写 NoSQL 的数据库系统. N ...