阿不

用勤奋寻找未来

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  181 随笔 :: 0 文章 :: 2308 评论 :: 75 引用

  在我的随笔《Page,你是怎样处理回发事件的?》中曾提出一个疑问,如何得到引起页面PostBack的控件?通过阅读Page类的源码,误打误撞,无意中看到了__EVENTTARGET和__EVENTARGUMENT这两个常量的定义,并通过调试分析页面,知道了通过Request.Form[“__EVENTTARGET”]可以获取到触发页面PostBack的事件源(控件的ID)。对于一般的控件,这样就可以了,唯有Button和ImageButton触发的PostBack无法通过这种方式获取到它们的ID,起初还以为是它们实现的接口的不同而产生PostBack方式的不同。刚刚在AspAlliance.看到一篇关于__doPostBack的文章(原文:《Understanding the JavaScript __doPostBack Function》),才真正明白了页面PostBack的内在机制,疑团也终于解开了。下面来简单看一下页面PostBack的原理,和Button,ImageButton PostBack的特殊性。

   __doPostBack是一个纯粹并且是非常简单的javascript函数,大部分的页面PostBack都是由它触发的。注意,这里是“大部分”,因为只有两个Web Server Control    会自己触发页面的PostBack,其它的所以控件都是通过__doPostBack函数触发页面的PostBack,那先来看一下这个函数的定义吧:

CODE1:

<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />

<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />

function __doPostBack(eventTarget, eventArgument) {

if (!theForm.onsubmit || (theForm.onsubmit() != false)) {

theForm.__EVENTTARGET.value = eventTarget;

theForm.__EVENTARGUMENT.value = eventArgument;

theForm.submit();

}

}

   通过上面的代码可以看到,__doPostBack带有两个参数,eventTarget是标识将要引发页面PostBack的控件ID,eventArgument参数提供了在引发页面PostBack事件时所带的额外参数。当然这个函数被函数时,这两个参数的值将赋值给页面的两个隐含变量__EVENTTARGET和__EVENTARGUMENT,然后调用页面的submit方法提交页面表单。这就是为什么我们可以通过Request.Form[“__EVENTTARGET”]获取得到引发页面PostBack的控件ID的原因。

   了解了__doPostBack函数后,我们可以很容易的利用它非常方便地自己触发自定义的PostBack事件。那上面也说了,大部分的控件都是调用这个方法来引了页面的PostBack,只有两个控件是例外,Button 和 ImageButton,正是因为它们不是通过调用__doPostBack来回发事件,所以通过表单隐含变量__EVENTTARGET和__EVENTARGUMENT是无法获取得到引发PostBack的Button或ImageButton的ID和参数值的,只有通过下面的方式才能得它们的实例,进而判断是哪个控件引发的PostBack的:

CODE2:

foreach (string str in Request.Form)

    {

    Control c = Page.FindControl(str);

if (c is Button)

{

control = c;

break;

}

}

   为什么能通过枚举Request.Form集合的Key值,查找到的回发事件源呢?在这里Button和ImageButton又有一些不同。Button控件引发的PostBack,会将Button本身的ID作为Request.Form的一个Key,它的Value是Button的Text属性值,回传给服务器,这样服务器就可以通过枚举Request.Form的Key值,去查找出控件实例,判断是否为Button控件,进而得到是哪个控件引发的PostBack事件。而ImageButton的不同就在于,它不仅仅是用ImageButton的ID作为Request.Form的Key,它是用ImageButton的ID加上.x和.y,作为Key,在Request.Form添加两上键值对,这两个键值对的值应该是标识ImageButton的图片大小。同样的,了解了这个规律后,我们仍然可以通过一定的方式得到是否是由ImageButton引发的PostBack。

总结:理解并掌握__doPostBack原理对我们更加了解Page的事件模型有非常大的帮助,并且也是我们进一步利用好页面的PostBack事件的一个重要基础。在整个asp.net页面PostBack模型中,只有Button和ImageButton是个例外,其它的控件都是一样的,也就是使用__doPostBack函数。在当我们需要通过__EVENTTARGET取得到事件源控件的话,这点是特别要注意的。

LookIntoDoPostBack.zip

阿不 http://hjf1223.cnblogs.com
posted on 2006-07-05 22:48 阿不 阅读(6878) 评论(33)  编辑 收藏 网摘 所属分类: .Net相关技术

评论

#1楼 2006-07-06 08:51 铱星      
不错
  回复  引用  查看    

#2楼 2006-07-06 09:16 brightheroes
Button这个Control,实现了IPostBackHandler这个接口。
页面会用一个数组来记录这些Control的ID。
通过.Form的Key传递回来的ID,和这些ID进行匹配,然后判断转向适当的Click事件。

  回复  引用    

#3楼 2006-07-06 09:34 浪子      

Control control = null;
            
bool findControl = false;
            
foreach(string controllName in this.Request.Form)
            
{
                control 
= this.FindControl(controllName);
                
if (control is IPostBackEventHandler)
                
{
                    findControl 
=true;
                    
break;
                }

            }

            
// Another try
            if (!findControl && this.Request.Form["__EVENTTARGET"]!=null)
            
{
                control 
= this.FindControl(this.Request.Form["__EVENTTARGET"].Replace(this.UniqueID+ ":"""));
            }




  回复  引用  查看    

#4楼 2006-07-06 09:40 MS的明天      
讲解的很详细。
  回复  引用  查看    

#5楼[楼主] 2006-07-06 09:51 阿不      
@brightheroes
在.NET 2.0 的类库中是没有IPostBackHandler这个接口的。
另外,通过实现接口的不同来分析为PostBack行为好像不是很妥当,你可以看一下我文章引用的我前一篇的问题描述。

  回复  引用  查看    

#6楼 2006-07-06 11:51 e旋风      
不错~

那么不用最新的AJAX技术,使用javascript的onblur也可以去触发一个服务器端的方法或事件

你可以在页面上放一个LinkButton
然后设置它的Text为""
然后在他的点击事件内写你的服务器端方法
然后
<input type="text" onblur="__doPostBack('你的linkbutton的ClientID','');">

就可以了


  回复  引用  查看    

#7楼 2006-07-06 12:09 Derek[未注册用户]
imagebutton的x/y是点击的位置(相对图片左上角)不是图片的大小
  回复  引用    

#8楼[楼主] 2006-07-06 12:34 阿不      
@Derek
谢谢,起初我也是认为是这样的。看起来这样比较合理。

  回复  引用  查看    

#9楼[楼主] 2006-07-06 12:36 阿不      
@e旋风
原理上是这样的。

  回复  引用  查看    

#10楼 2006-07-06 13:05 潘胜国      
如果直接调用__ddPostBack那页面上的验证控件都会失效的,
  回复  引用  查看    

#11楼 2006-07-06 13:45 brightheroes
@L.Z.
我说的不全,是IPostBackEventHandler接口……

  回复  引用    

#12楼[楼主] 2006-07-06 14:23 阿不      
@brightheroes
这样也解释不通啊。LinkButton也实现了IPostBackEventHandler接口啊。

另外:L.Z.是什么意思?

  回复  引用  查看    

#13楼 2006-07-06 15:51 维生素C.NET      
@阿不
L.Z.是楼主的意思.
HtmlButton也是实现了这个接口的,还有像Calendar类.

@Derek
那个应该是HTML本身的图片可以选择不同的区域来做不同的连接,这个坐标是不是用来判断指向的连接的位置的?

  回复  引用  查看    

#14楼[楼主] 2006-07-06 17:26 阿不      
@维生素C.NET
thanks,比较少逛论坛,这些“专业述语”还没完全看懂。

对于两个值,还需要再查找一些资料。因为在没有图片的情况下,这两个值是为空的,没有值的。

  回复  引用  查看    

#15楼 2006-07-06 21:58 生活、工作      
http://istep.cnblogs.com/archive/2006/03/09/335963.html">http://istep.cnblogs.com/archive/2006/03/09/335963.html
  回复  引用  查看    

#16楼 2006-07-07 15:01 肥鱼      
2.0的页面上就没有这个脚本存在
  回复  引用  查看    

#17楼[楼主] 2006-07-07 15:57 阿不      
@肥鱼
怎么会没有呢?你仔细查看一下页面代码。我现在就是用2.0的,我明明看到有这个函数存在的。

  回复  引用  查看    

#18楼 2006-07-08 09:06 随心所欲      
我记得在aspx页面的生命周期里面有过解释。
如果自己写一个IHttpHandler,可能理解会更深。

  回复  引用  查看    

#19楼[楼主] 2006-07-08 10:39 阿不      
@ 随心所欲
这个跟IHttpHandler没有特别直接的联系。实际上Page也是一个IHttpHandler。

  回复  引用  查看    

#20楼 2006-07-09 10:48 随心所欲      
@阿不
Page就是一个IHttpHandler。
如果你写一个IHttpHandler,你就会遇到Page所要处理那些问题:解析来自页面的字符串的命令,然后代理到还原后的.net对象的事件中。
那么你就需要写这样一个函数来处理,写来写去,结果大致就和DoPostBack函数一样了。
这就是我的意思,这时候你对这个函数的理解就会更深了。

  回复  引用  查看    

#21楼 2006-07-09 10:49 随心所欲      
@肥鱼
如果你的页面上根本没有任何需要回发处理的,页面上可能没有这个函数(或者在其他资源文件里)

  回复  引用  查看    

#22楼 2006-07-09 10:55 随心所欲      
2.0里面没有 IPostBackEventHandler? 这个好像不对吧。
这是一个例子:
public class MyView : System.Web.UI.Control, System.Web.UI.IPostBackEventHandler

public void RaisePostBackEvent(string eventArgument)
{
this.Initialize();
string[] parts = eventArgument.Split('=');
string commandName = parts[0];
string value = (parts.Length > 1 ? parts[1] : null);
switch (commandName .ToLower())
{
case "Command1":
.......

首先要继承自IPostBackEventHandler,然后再实现函数里面,写出自己对命令字符串的解析和处理。

  回复  引用  查看    

#23楼[楼主] 2006-07-09 11:57 阿不      
@随心所欲
是没有 IPostBackHandler 接口,不是没有IPostBackEventHandler

  回复  引用  查看    

#24楼 2006-07-20 15:19 啊啊[未注册用户]
请问几个问题:

在你的例子中,点服务器button的时候,在后台
foreach (string str in Request.Form)
{ //.. }
循环里面,怎么得到的都是一些(我看不明白)??
_EVENTARAGET
_EVENTARGUMENT
_LASTFOCUS
_DROPDOWNLIST(列表控件)
_BUTTON(按钮)
_EVENTALIDATION
这些东西是什么意思啊??或则说是不是postback,都要回传这些,除了你激发的控件_EVENTARAGET,_EVENTARGUMENT

  回复  引用    

#25楼[楼主] 2006-07-20 18:59 阿不      
@啊啊
是的,这些是表单提交时的表单参数。

  回复  引用  查看    

#26楼 2006-07-31 23:15 メ冰枫ぱ雪      
Foreach Form 中的元素,想的一样。。下面的代码明天看。。 很不错。。
  回复  引用  查看    

#27楼 2006-08-07 14:30 alexn[未注册用户]
你好,我想问一下
利用__doPostBack能不能指定要调用server端的某个处理函数?
还是只能在PageLoad里检查EventTarget,再去调相应的函数

  回复  引用    

#28楼 2006-08-08 20:46 阿旺[未注册用户]
////
这是前台页面中的代码:
<body>
<form id="form1" runat="server">
<atlas:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<input type="hidden" id="_EVENTTARGET" name="_EVENTTARGET" value="" />
<input type="hidden" id="_EVENTARGUMENT" name="_EVENTARGUMENT" value="" />
<script language ="javascript" type="text/javascript" >
function _doPostBack(_eventTarget,_eventArgument)
{
if(!theForm.onSubmit|| (theForm.onSubmit !=false) )
{
theForm._EVENTTARGET.Value = eventTarget;
theForm._EVENTARGUMENT.Value = eventArgument;
theForm.Submit();
}
}
</script>
</div>
</form>

<script type="text/xml-script">
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
<references>
</references>
<components>
</components>
</page>
</script>
</body>

//////这是后台中的代码:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
foreach (string str in Request.Form)
{
Control c = Page.FindControl();
if(c is Button)
{
Control = c;
break;
}

}
}
}
////////////////引用的命名空间为:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.UI.Control;
编译后出现下面的错误:
Error 1(即using System.Web.UI.Control;)
A namespace does not directly contain members such as fields or methods
出借何在>?????

  回复  引用    

#29楼 2006-08-08 20:52 阿旺[未注册用户]
Unhandled exception at 0x7c815dea in devenv.exe: 0xE0434F4D: 0xe0434f4d.

这是一个什么错误提示??
出错在那??谢谢!!!

  回复  引用    

#30楼[楼主] 2006-08-09 16:29 阿不      
@alex
不行的,只能通过你后面所说的那种方法。

  回复  引用  查看    

#31楼[楼主] 2006-08-09 16:33 阿不      
@阿旺
你的第一个错误是提示说,引用的类没有包含你调用的方法,可能是命名空间没有正确引用吧。

第二个问题不是程序本身的问题,是VS2005的异常。

  回复  引用  查看    

#32楼 2007-12-05 10:24 JustDI      
@阿不
例子里面为什么总是获取不到Button2的EventArgument值呢?

  回复  引用  查看    

#33楼[楼主] 2007-12-05 10:50 阿不      
@ JustDI
Button2的EventArgument可以取得到值是:My Argument
Button1的EventArgument是取不到,因为服务器端的button使用不同的postback方法。

  回复  引用  查看    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 443761




相关文章:

相关链接: