__doPostBack方法解析 __VIEWSTATE __EVENTTARGET __doPostBack __EVENTARGUMENT

关于这个的另一篇博客:http://www.cnblogs.com/Silicon-Fado/archive/2009/04/21/1440437.html

__VIEWSTATE:页面状态信息在客户端的存储(ViewState中存储的信息, EnableViewState="true"的控件状态信息).
__EVENTTARGET:页面回传触发事件 页面回传触发事件:

__doPostBack('Button2','')表示调用按钮Button2在后端的所对应的单击事件 控件回传触发事件:

__doPostBack('TEST1$Button1','')表示调用TEST1控件中的Button1按钮的Click方法
__EVENTARGUMENT:页面回传触发事件时所带的参数 如:__doPostBack('Button1','aa')在后端可以使用Request.Form["__EVENTARGUMENT"]来取得
.net自动生成的一些客户端的代码 用来回传数据和自己带的一些脚本函数 
=====================================================================

今天工作时遇到一个需要根据Gridview具体内容来判断是否弹出窗口,而Gridview中包含分页、排序等,它们并不能直接从查询字符串、或表单简单的分析出。这是因为存在__doPostBack方法,以及和其紧密关联的__ EVENTTARGET和__ EVENTARGUMENT。


function __doPostBack(eventTarget, eventArgument)的eventTarget参数是GridView控件的名字,eventArgument参数是命令字。当如果是删除时,eventArgument参数是Delete开头;当如果是插入时,eventArgument参数是Insert开头;当如果是编辑时,eventArgument参数是Edit开头;当如果是选择时,eventArgument参数是Select开头。 
 
============================================================
客户端触发事件后调用__doPostBack方法,将表示触发的控件源的eventTarget 和事件参数eventArgument分别付给两个隐藏域__EVENTTARGET和__EVENTARGUMENT,然后提交Form,在服务端根据 __EVENTTARGET和__EVENTARGUMENT来判断是哪个控件的什么事件触发了。

< script language="javascript">  
 
function __doPostBack(eventTarget, eventArgument)
 
{
 
  var theform = document.WebForm2;
 
  theform.__EVENTTARGET.value = eventTarget;
 
  theform.__EVENTARGUMENT.value = eventArgument;
 
  theform.submit();
 
  }
 
< /script>

 

=================================================================Asp.net的postback机制我们知道Asp.net输出到客户端时都会被转化为HTML,页面Render到Client后,Client的HTML代码将包含如下代码:

复制代码
  <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />

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

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTA0NDQ2OTE5OWRk281L4eAk7iZT10hzg+BeOyoUWBQ=" />

<script type="text/javascript">

<!-- 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>
复制代码

 

其中隐藏字段_EVENTTARGET代表触发事件的控件。_EVENTARGUMENT代表事件的额外参数。为了页面能在PostBack后依然能读取服务器控件原有的状态数据,Asp.net中使用了ViewState技术,而ViewState技术本质上是用一个默认名称为__VIEWSTATE的Hidden类型表单域来保存和传递数据(这些数据是经过了序列化后Base64编码的字符串值)。控件的事件被Render后事件变成javascript:__doPostBack('Button1','')

例如下面的样子

<input type="button" name="Button1" value="Button1" onclick="javascript:__doPostBack('Button1','')" id="Button1" />

===============================================================================================

这地方可看令一篇博文:http://www.cnblogs.com/Silicon-Fado/archive/2009/04/21/1440437.html

只有两个Web Server Control 会自己触发页面的PostBack,其它的所有控件都是通过__doPostBack函数触发页面的PostBack,页面解析时回将该类生成一个__doPostBack(eventTarget, eventArgument)方法。eventTarget是引起回送的控件的ID,eventArgument是回调参数(与控件相关的附加数据)。这两个参数分别由隐藏的两个表单域__ EVENTTARGET和__ EVENTARGUMENT保存。使用这两个隐藏的表单可以查找引起页面回送的控件ID和回送时的参数。

当你触发__doPostBack事件时,遍历this.Request.Form.AllKeys,你查看到这两个隐藏的表单。

由于最终呈现给浏览器的内容都是html内容,采用asp.net技术也不能例外.要实现webcontrol的postback机制.只能在原来的submit上做文章。

我看到,asp.net现在页面上添加了两个hidden input,这两个input分别用来存放触发postback的control的ID和参数.这就是我们大部分人认识到的:

__doPostBack(obj1,obj2)的第一个参数是控件ID,第二个参数是postback的参数.然后就可以在后台用Request.Form["__EVENTTARGET"]和Request.Form["__EVENTARGUMENT"]取得控件ID和参数.

很简单就实现了看似很神奇,以为内部有什么高深的处理的过程!如此轻巧的实现了asp.net的postback机制,佩服佩服!只要我们看懂了上边的代码,对__doPostBack的使用就应该不是什么难事了.可以说__doPostBack就是这么简单的一回事.-_-||

不过,另外要注意的就是asp.net的webcontrols中,Button和ImgButton是异类,它们不是利用__doPostBack来实现postback的.为什么这样,可能因为Button在html中本来就是有触发submit事件的功能吧.asp.net不过是要令原来html中一些不能触发submit的东西submit,才弄出了__doPostBack来实现.对于原来就能submit的Button,又何必多此一举呢.
如上写法可以在后台找到Button.为什么这样? 不知道,呵呵. 在Button的提交过程中,Button会将Button本身的ID作为Request.Form的一个Key,它的Value是Button的Text属性值,回传给服务器.所以可以在后台循环Form.Keys取到所提交的Button,以执行相应的函数.ImgButton也差不多,不同就在于,它不是用ImageButton的ID作为Request.Form的Key,它是用ImageButton的ID加上.x和.y作为Key,在Request.Form添加两上键值对,这两个键值应该是对应ImageButton的图片大小的,了解了这个规律后,我们仍然可以通过一定的方式得到是否是由ImageButton引发的PostBack.

 

如下面的我写的一个简单页面的例子,

(1)页面中的下拉列表呈现在hyml中是这样的

复制代码
<select name="DropDownList2" onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;DropDownList2\&#39;,\&#39;\&#39;)&#39;, 0)" id="DropDownList2">

<option value="--请选择--">--请选择--</option>

<option value="家用家具1">家用家具1</option>

<option selected="selected" value="家用家具2">家用家具2</option>

<option value="家用家具3">家用家具3</option>

<option value="家用家具4">家用家具4</option>



</select>
复制代码

可看到

onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;DropDownList2\&#39;,\&#39;\&#39;)&#39;, 0)" id="DropDownList2">

此处下拉列表通过__doPostBack函数触发页面的PostBack,页面解析时回将该类生成一个__doPostBack(eventTarget, eventArgument)方法。

(2)对于按钮呢,则是这样的

 

<input type="submit" name="Button1" value="确认" id="Button1" />

按钮没有用到__doPostBack,原因是asp.net的webcontrols中,Button和ImgButton是异类,它们不是利用__doPostBack来实现postback的.为什么这样,可能因为Button在html中本来就是有触发submit事件的功能吧.asp.net不过是要令原来html中一些不能触发submit的东西submit,才弄出了__doPostBack来实现.对于原来就能submit的Button,又何必多此一举呢.

 ===================================================================================================

当按钮被点击后,触发了__doPostBack事件,_doPostBack事件把表单提交给Server, Server端通过__EVENTTARGET这个hidden field的值找到对应的Server端的Control.接下来Server查看Control是否实现调用Page的RaisePostBackEvent,这个函数的定义如下:

复制代码
protected virtual void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)

{

sourceControl.RaisePostBackEvent(eventArgument);

}
复制代码

 

函数调用本控件内的

复制代码
protected virtual void RaisePostBackEvent(string eventArgument)

{

base.ValidateEvent(this.UniqueID, eventArgument);

iif (this.CausesValidation)

{

this.Page.Validate(this.ValidationGroup);

}

this.OnClick(EventArgs.Empty);

this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));

}

posted on 2018-10-12 08:28  asdyzh  阅读(447)  评论(0编辑  收藏  举报

导航