这里需要提一下的是,asp.net编程提供了服务端控件和客户端控件的说法,其实还是脱离不了HTML的本质,客户端和服务端需要交互必须要提交,提交有两种方式get和post。get就是通过向服务端发送连接地址,服务端通过地址的参数来获得信息的,一般这些参数都是明文,能在浏览器地址栏看到。而post是通过表单的input等元素提交到服务端的页面的,这些数据一般是看不到的。asp.net的服务端控件其实就是对一般的HTML控件做了个包装,大体是通过隐藏控件提供控制的参数的。
这里介绍一个常用的函数_doPostBack,这个函数如果是ASP.Net render出来的页面就是自动产生这个函数,比如有带autopostback属性的控件,且其属性为true的页面,带编辑列的datagrid页面。__doPostBack是通过__EVENTTARGET, __EVENTARGUMENT两个隐藏控件向服务端发送控制信息的。__EVENTTARGET为要调用控件的名称,如果要调用的控件是子控件,用''$'或':'分割父控件:子控件,__EVENTARGUMENT是调用事件时的参数。
下面演示下如何调用后台事件:
1.新建工程
2.拖入一个服务端Button1,一个DropDownList1和一个客户端Button
3.设置DropDownList1的AutoPostBack属性为True,Button1的Visible为False
4.双击Button1,在事件里写下Response.Write("hello:" );
5.页面的HTML里找到客户端Button,写入οnclick="__doPostBack('Button1','')"
6.编译,运行,点击Button是不是出现了"Hello"
7.查看源代码,发现里面多了下面行
<script language="javascript">
<!--
function __doPostBack(eventTarget, eventArgument) {
var theform;
if (window.navigator.appName.toLowerCase().indexOf("netscape") > -1) {
theform = document.forms["Form1"];
}
else {
theform = document.Form1;
}
theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
// -->
</script>
以及两个隐藏控件
<input type="hidden" name="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" value="" />
值得注意的是,_doPostPack的第一个参数是大小写不敏感的。细心的人会发现,在__doPostBack里,提交调用的是theform.submit(),这样就导致对Form的onsubmit事件校验失效了,幸好这个问题在asp.net 2.0已经修复了。这里提供一个替换的解决办法,在Form的最下面插入下面的代码,这段代码在保证不管是不是render出来的页面均有效
【
用submit提交是不会触发onsubmit事件的,onsubmit是用submit按钮提交才触发
<form action="bb.asp" name="aa" οnsubmit="alert('aa')">
</form>
<SCRIPT LANGUAGE="JavaScript">
<!--
aa.submit();
//-->
</SCRIPT>
】
<script language="javascript">
<!--
function __doPostBack_Ex(eventTarget, eventArgument)
{
var theform;
if (window.navigator.appName.toLowerCase().indexOf("netscape") > -1) {
theform = document.forms[0];
}
else {
theform = document.forms[0];
}
if(!theform.__EVENTTARGET)
{
theform.appendChild(document.createElement("<input type='hidden' name='__EVENTTARGET'>"));
}
if(!theform.__EVENTARGUMENT)
{
theform.appendChild(document.createElement("<input type='hidden' name='__EVENTARGUMENT'>"));
}
theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
theform.__EVENTARGUMENT.value = eventArgument;
if ((typeof(theform.onsubmit) == "function"))
{
if(theform.onsubmit()!=false)
{
theform.submit();
}
}
else
{
theform.submit();
}
function __doPostBack(eventTarget, eventArgument)
{
__doPostBack_Ex(eventTarget, eventArgument);
}
}
// -->
</script>
------------------------------------------------------------------------
http://hjf1223.cnblogs.com/archive/2006/06/20/430475.html
无刷新“页面跳转”
无刷新转页面? 这是我前些天提出一个想法。为什么会有这样的想法呢?主要是考虑到目前如果使用Atlas作开发的话,那就不可以避免的要下载它的脚步库。一般情况下,我们都会下载的是Atlas.js(少数情况才会下载AtlasRuntime.js),这个文件就要238KB,如果是Debug版本的程序的话,那么将会下载Debug版本的Atlas.js,而这个文件就要360KB。(所以要发布asp.net程序时,设置web.config的debug="false"很重要的.)再得寸进尺点,原来每次转页面时,都需要重新下载所以有CSS,JS,Image,更新ViewState等等,这些都需要花费非常多的资源和时间(可以通过Fiddler查看一下访问一次页面的过程)。那么,是不是有一种办法,做到既可以改变页面的功能,又可以不重新刷新页面呢?这样效率那该提高多少啊?
不用框架页面,那就尝试使用动态加载用户控件的方式吧。主要思路是这样的,把原来做在页面上功能封装到一个用户控件去,利用导航菜单来动态加载不同的用户控件。由于大部分情况下,页面的框架基本都是一样的,不同的功能页面也就是部份内容的不同,和执行不同的功能而已。这就是给这样的思路提供了一个前提环境条件,做一个页面(功能类似一个MasterPage),在这个页面上做好页面总体布局,在需要动态改变的位置上放一个PlaceHolder,用Atlas UpdatePannel包起来,设置合适的更新条件刷新这块区域的内容。
简单来看一下实现步骤。新建一个Web Site工程,创建三个不同功能的WebUserControl,在Default.aspx页面上放一个Menu控件做导航,利用它的MenuItemClick事件作导航,而不要直接设置NavigateUrl属性。
1 <asp:Menu ID="Menu1" runat="server" OnMenuItemClick="Menu1_MenuItemClick">
2 <Items>
3 <asp:MenuItem Text="WebUserControl1" Value="WebUserControl1.ascx"></asp:MenuItem>
4 <asp:MenuItem Text="WebUserControl2" Value="WebUserControl2.ascx"></asp:MenuItem>
5 <asp:MenuItem Text="WebUserControl3" Value="WebUserControl3.ascx"></asp:MenuItem>
6 </Items>
7 </asp:Menu>
在页面的合适位置上放一个asp:PlaceHolder 控件,将它包含在atlas:UpdatePanel里面,设置好EventTrigger,作为这部份的刷新条件:
<atlas:UpdatePanel ID="UpdatePanel1" runat="server" Mode="Conditional">
<Triggers>
<atlas:ControlEventTrigger ControlID="Menu1" EventName="MenuItemClick" />
</Triggers>
<ContentTemplate>
<div style="float: left; margin-left: 10px; width: 300px; height: 300px;">
<asp:PlaceHolder ID="PlaceHolder1" runat="server" EnableViewState="false"></asp:PlaceHolder>
</div>
</ContentTemplate>
</atlas:UpdatePanel>
接下来就如何动态加载UserControl的问题了,动态加载UserControl需要注意的一些细节在这篇文章里(Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项)已经一个很好的讨论了。我的做法重写CreateChildControls方法,然后在这个方法里动态加载用户控件。但是还需要解决一个问题,如何才能知道要加载哪个用户控件呢?因为根据页面的事件模型,控件的处理事件是在页面加载,处理完后才被处理的,也就Menu1_MenuItemClick事件是晚于CreateChildControls方法被执行的。那在CreateChildControls方法怎么才知道要加载的控件的呢?那么如果能在这个方法中得到引发页面回发的事件源和参数就可以解决了。经过调试和查看Page类的源代码,发现有在Page类中有这两个常量定义,postEventArgumentID (值为:"__EVENTARGUMENT")和postEventSourceID(值为: "__EVENTTARGET")。既然有这两个常量定义,肯定也可以得到它们的请求值,最终找到了可以在Request.Form取到他们的值,而且也是我希望的值。来看看页面代码:
protected string ControlType
{
get
{
if (ViewState["ControlType"] != null)
{
return ViewState["ControlType"].ToString();
}
return "";
}
set
{
ViewState["ControlType"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)
{
}
protected override void CreateChildControls()
{
base.CreateChildControls();
if (Request.Form["__EVENTTARGET"] != null && Request.Form["__EVENTTARGET"].Equals("Menu1"))
{
ControlType = Request.Form["__EVENTARGUMENT"];
}
if (!string.IsNullOrEmpty(ControlType))
{
ITemplate m_template = Page.LoadTemplate(ControlType);
m_template.InstantiateIn(PlaceHolder1);
//PlaceHolder1.Controls.Add(Page.LoadControl(ControlType)); 这种加载方法也可以
}
}
不是很复杂的代码,应该能一看就明白了。这里就不再浪费篇幅了。
总结:通过这种方法来改变页面功能的好处是,可以大大减少加载页面的时间,减小服务器的压力。但是可能还有很多我没有考虑到的问题会出现。希望能有一个讨论的结果。另外,在加载用户控件的部分前面,由于前面没有看到那两个常量,使用了另一种方法,但是当从一个UserControl转到另一个UserControl时,新的UserControl的第一次回发事件将不会被执行,这个问题一直没能解决。在附下载的例子中的default.aspx就还存在这样的问题,找到问题的起因,但是一直没能明白过来。
---------------------------------------------------------------------------
http://hjf1223.cnblogs.com/archive/2006/06/21/432186.html
Page,你是怎样处理回发事件的?
在我的前一篇POST( 无刷新"页面跳转")中有提到Page类中的两个常量(postEventArgumentID="__EVENTARGUMENT")和postEventSourceID="__EVENTTARGET"),通过Request.Form(或Request.Params)可以取到它们的值,它们的值的作用是可以知道是哪个控件引发了当前页面的回发。对于Menu控件,这两个值非常好。对于LinkButton,可以取到 postEventSourceID有内容,是LinkButton的ID。但是对于Button和ImageButton,就都取不到这两个值了。附件中的页面就是这样一个例子。
我分析了一下,它们还是有一定的共同和不同点的。Menu,LinkButton都实现了IPostBackEventHandler ,而Button,ImageButton除了实现这个接口外,还实现了IPostBackDataHandler。由于平常对控件这方面了解比较少,到目前为止还没有真正理解控件机制,即使用Reflector仔细查看了一下Page的反编译代码,关键在ProcessPostData方法,但还是无法找出问题所在。为什么多实现了一个接口,差别咋就这么大呢?IPostBackDataHandler多做了什么事了呢?
另外,想在CreateChildControls方法中得到引发页面回发的Button或ImageButton该怎样做比较合适呢?
----------------------------------------------------------------------------
http://blog.csdn.net/aboutblog/archive/2006/09/27/1293926.aspx【看页面】
深入理解 __doPostBack
在我的随笔《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取得到事件源控件的话,这点是特别要注意的。
----------------------------------------------------------------
http://hi.baidu.com/liuzhong1984/blog/item/caea9326c9dc741f8a82a108.html
_dopostback这个前台函数的功能,主要是用于web控件的postback,它是通过__eventTraget,__eventArgument两个隐藏控件向服务端发送控制信息的。
__eventTraget:为要调用控件的名称,如果要调用的控件是子控件,用''$'或':'分割父控件:子控件;
__eventArgument:调用事件时的参数;
__doPostBack最简单的使用方法:
1、在页面上划一个能产生 __dopostback函数的控件。(并不是所有的web控件都是用__dopostback产生事件回发),我个人喜欢用linkbutton,然后把text属性设为空值,如果隐藏控件的话,那么__dopostback函数不会产生。
2、然后在你想要触发postback事件的控件ID,写入到如下函数调用中:
__doPostBack('imgMap','');
在这里imgMap是我要回发的控件。
3、现在就可以在一个前台事件里调用
__doPostBack('imgMap','');
4、在后台imgMap_Click事件中编写代码就行了
doPostBack
在.NET中,所有的服务器控件提交到服务器的时候,都会调用__doPostBack这个函数,所以灵活运用这个函数对于我们的帮助还是很大的。
比如,在我们写程序的时候经常会需要动态的生成一些控件,最简单的方法就是通过一个字符串,比如string strButton = <input type =”button” ID=”button1”>,然后输出到页面,但是如果我们需要这个控件来执行一些服务器的功能,就比较困难了。这里我们就可以用过借用__doPostBack这个函数来完成。接下来我觉个例子来说明一下具体如何调用。
既然要在服务器端运行那么,我们可以声明一个不可见的LinkButton控件,那通常,我们希望一个控件不可见,通常都是把visible属性设为false。但是在这里我们把LinkButton的Text属性设置为空,来是这个LinkButton不可见(为什么要这么设置,而不是直接设置visible属性,我会在下面说明),接下来我们可以在LinkButton里面写一些服务器端的代码。然后就是如何通过我们动态生成的客户端控件来调用LinkButton里面的功能,我们可以通过一个JavaScript函数来实现
function ExcuteOnServer()
{
//第一个参数是你希望提交到服务器的控件的ID号,第二个参数是事件参数
__doPostBack('LinkButtonID','');
}
接下去我们只需要在动态生成的这个Button控件的onclick事件中写上οnclick=”JavaScript:ExcuteOnServer();“,这样当我们点击这个动态生成的客户端控件的时候,他便会执行LinkButton中的代码。
这样便实现了动态生成的客户端控件提交到服务器端的功能。
最后要说一下的就是为什么希望LinkButton控件不可见的时候,不是通过visible属性来完成的。因为当我们把visible属性设置为false的时候,浏览器在解析的时候,根本不会把这个控件放在页面上,也就是说这个控件是不存在的,所以我们在调用__doPostBack函数的时候,便会找不到控件。
__doPostBack(sender,args)函数基本使用方法
在项目中遇到很多地方需要做二次提交处理,经过研究和收集总结了客户端js利用__doPostBack(sender,args)函数来提交到服务器的方法。(不断补充中)
__doPostBack(sender,args)
sender:提交的控件
args: 事件参数。一般赋空值。
web.aspx页面上放置任何一个控件:
<asp:button id="btnTest"/>
VB页面代码中在Page_Load中添加:
Me.GetPostBackEventReference(btnTest);
C#:this.GetPostBackEventReference(this);
注意该语句不要放在 IF Not IsPostBack Then End IF 中。
C#中不需要上述步骤。
客户端调用js代码:__doPostBack("btnTest",""); 注意是双下划线。即可提交到服务器端。
调用该函数提交不会触发控件的任何js事件而直接进入服务器端。
可以利用该特性来做二次提交:
在button控件的Click事件中做一个标记利用hidden控件或其他方式保存一个Flag
__doPostBack提交则无此Flag
服务器端则根据该Flag来判断是button提交还是__doPostBack提交。
注意在后台处理__doPostBack提交的逻辑中将Flag刷新
---------------------------------------------------------------------------
http://hi.baidu.com/zhxhdean/blog/item/acef46c8a94e2f107f3e6f91.html
__doPostBack函数
在.NET中,所有的服务器控件提交到服务器的时候,都会调用__doPostBack这个函数,比如,我们经常需要动态的生成一些控件,最简单的方法就是Response.Write("<input type =/"button/" ID=/"button1/">);,然后输出到页面,但是如果我们需要这个控件来执行一些服务器的功能,就比较困难了。这里我们就可以用过借用__doPostBack这个函数来完成。
既然要在服务器端运行那么,我们可以声明一个不可见的Button控件,那通常,我们希望一个控件不可见,在这里我们把LinkButton的Text属性设置为空,来是这个LinkButton不可见(visible设成false的话会不被发送到客户端的),接下来我们可以在Button里面写一些服务器端的代码。然后就是如何通过我们动态生成的客户端控件来调用LinkButton里面的功能,我们可以通过一个JavaScript函数来实现
function ExcuteOnServer()
{
//第一个参数是你希望提交到服务器的控件的ID号,第二个参数是事件参数
__doPostBack('ButtonID','');
}
接下去我们只需要在动态生成的这个Button控件的onclick事件中写上οnclick=”JavaScript:ExcuteOnServer();“,这样当我们点击这个动态生成的客户端控件的时候,他便会执行LinkButton中的代码。
这样便实现了动态生成的客户端控件提交到服务器端的功能
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jamestaosh/archive/2009/08/18/4460158.aspx