老赵点滴


  先做人,再做技术人员,最后做程序员。
  我的理想:“让外国人看中国人写的技术书籍和文章”。Try as I might
posts - 287, comments - 10551, trackbacks - 137, articles - 6
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

  最近时间很少,而且总觉得没有什么题材可写。今天无意中看到了Aldebaran's Home提出的一个疑问,为什么在Form_Load方法中动态添加的AsyncPostBackTrigger会在经过一次异步刷新后就失效,导致第二次提交变成了普通的提交。我尝试了一下,果不其然。对ASP.NET AJAX程序集源码的分析之后,我得出了问题原因和解决方案,在这里和大家共享一下。

 

问题重现

  首先,我们来重现这个问题。新建一张页面,在aspx文件中输入以下代码:

aspx文件代码
<asp:ScriptManager ID="ScriptManager1" runat="server" />

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <%= DateTime.Now %>
    </ContentTemplate>
</asp:UpdatePanel>

<asp:Button ID="Button1" runat="server" Text="Button" />

 

  然后在Code Behind文件中输入以下代码:

Code Behind文件内容
protected void Page_Load(object sender, EventArgs e)
{
    AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
    trigger.ControlID = "Button1";

    this.UpdatePanel1.Triggers.Add(trigger);
}

 

  打开页面,第一次点击按钮之后页面进行了部分刷新,但是第二次点击按钮之后页面使用传统的方式进行了一次完整的PostBack。

 

问题分析

  问题分析是一个复杂的过程,虽然我得到结果只用了大约15分钟的,但是在这之前我已经花了无数的时间对ASP.NET AJAX的客户端代码和服务器端代码进行阅读和理解。因此,有些部分可能我只是一笔带过,详细的实现方式只能靠感兴趣的朋友自己去发现了。

  造成这个问题的原因,在于用户点击按钮提交信息之后,客户端的PageRequestManager逻辑无法察觉这个按钮的提交应该作为一次异步刷新处理。在页面第一次被打开时,页面的源代码中会出现这样的代码:

页面初始化部分代码
Sys.WebForms.PageRequestManager.getInstance()._updateControls(
    ['tUpdatePanel1'], // 页面中所有UpdatePanel的ID
    ['Button1'], // 页面中所有异步提交的元素ID
    [], // 页面中所有同步提交的元素ID
    90 // 异步更新超时时间
);

 

  正是因为这句代码,在页面第一次被打开之后,PageRequestManager记住了这么一件事情:“Button1造成的提交应该作为异步刷新处理”。因此,在Button1第一次被点击时,页面进行了异步刷新。但是,在这次异步刷新之后,PageRequestManager将会忘记所有的这些信息(UpdatePanel、异步提交元素、同步提交元素、超时时间),服务器端这时也会把新的信息给传输到客户端来。在这里,如果我们使用Web Development Helper查看在这次异步刷新时服务器端传回的信息就会一清二楚了,如图:

 

  可以看到,与asyncPostBackControlID一项对应的右侧内容空空如也,这表示服务器端根本没有将“Button1是异步提交的控件”这个信息告诉客户端——这也难怪在第二次点击按钮时,一个传统的PostBack发生了。

  从客户端角度发现问题只能进展到这里了,现在的问题变成了:为什么服务器端不把“正确信息”发送到客户端呢?答案似乎只有一个:“服务器端不认为Button1是个异步提交的控件”。我们知道,如果目前正在进行异步刷新,服务器端会“截获”页面的输出方法,以此自定义输出信息。分析那个方法(以及相关方法)之后可以得知,服务器端输出的是使用ScriptManager的RegisterAsyncPostBackControl方法注册过的控件。与之相同的是在页面第一次被打开时注册在页面中的JavaScript脚本。

  问题进一步发展下去了,为什么Page_Load方法中的代码总是会执行的,但是在异步刷新时,RegisterAsyncPostBackControl方法就少了一次调用呢?

  有一定经验的朋友们应该可以隐隐察觉到,这个问题似乎和控件的生命周期有关。没错,这个问题涉及到UpdatePanel处理Trigger的“时机”。在UpdatePanel的Initialize方法中,会(间接)调用每个Trigger的Initialize方法进行初始化。而正是在AsyncPostBackTrigger类的Initialize方法中,ScriptManager的RegisterAsyncPostBackTrigger方法被调用了,它的ControlID所指的控件因此被注册为“异步提交”的控件。

  UpdatePanel的Initialize方法会在UpdatePanel生命周期的两个环节中被调用,如下:

UpdatePanel部分代码
protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    this.RegisterPanel(); // Initialize方法将会被间接调用
    this.CreateContents(base.DesignMode);
}

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    if (!base.DesignMode && !this.ScriptManager.IsInAsyncPostBack)
    {
        this.Initialize();
    }
}

 

  问题的关键就在UpdatePanel的OnLoad方法中。可以看到,按照OnLoad方法的逻辑,只有不在异步提交的情况下(!this.ScriptManager.IsInAsyncPostBack),Initialize方法才会被调用。如果我们正在异步刷新呢?当然就没有效果了。而在OnInit方法中如果要让它初始化Trigger,则必须满足两个条件:首先是PostBack,其次该UpdatePanel是动态添加的。这段逻辑非常复杂,由此也可以看出ASP.NET页面的生命周期虽然完善,但是非常复杂,控件的很多细节甚至只能通过查看代码才能看到。

 

解决方案

  明白问题所在之后,解决方案自然也就容易得到了。

  首先,如果可行的话,我们可以在页面的OnInit方法中动态添加Tirgger,这样就可以保证在UpdatePanel的Init过程中Trigger被初始化,如下:

在OnInit方法中添加Trigger
protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
    trigger.ControlID = "Button1";

    this.UpdatePanel1.Triggers.Add(trigger);
}

 

  可惜,很可能我们的操作需要添加到依赖到别的信息,因此我们还是必须在页面Load时添加Trigger。那么,我们可以手动调用一下ScriptManager的RegisterAsyncPostBackControl方法,如下:

手动调用RegisterAsyncPostBackControl方法
protected void Page_Load(object sender, EventArgs e)
{
    AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
    trigger.ControlID = "Button1";
    this.UpdatePanel1.Triggers.Add(trigger);

    this.ScriptManager1.RegisterAsyncPostBackControl(this.Button1);
}

 

  严格说来,这是一种错误的做法。因为调用了RegisterAsyncPostBackControl方法只是把Button1作为了“异步提交”的控件,但是却没有建立起它与UpdatePanel的关系,这导致UpdatePanel可能不会被正确刷新。(补充:实践证明,这么做在很多情况下甚至会抛出异常。)

  因此,最正确的方法,可能就是通过反射来调用UpdatePanelTrigger的Initialize方法了,如下:

使用反射调用Initialize方法
private static MethodInfo triggerInitMethod = 
    typeof(UpdatePanelTrigger).GetMethod(
        "Initialize",
        BindingFlags.NonPublic | BindingFlags.Instance);

protected void Page_Load(object sender, EventArgs e)
{
    AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
    trigger.ControlID = "Button1";

    this.UpdatePanel1.Triggers.Add(trigger);

    if (ScriptManager.GetCurrent(this).IsInAsyncPostBack)
    {
        triggerInitMethod.Invoke(trigger, null);
    }
}

 

  至此,问题解决。而在解决了这个问题之后,Web Development Helper捕捉到的信息,应该如下图所示。

Feedback

#1楼    回复  引用  查看    

2007-03-08 08:25 by 命运有自己的梦!      
我正在为怎样动态的添加异步或者同步的按钮到UpdatePanel感到困惑,想不到看到您的文章后能解决了,先谢了!

#2楼    回复  引用  查看    

2007-03-08 08:51 by 非我      
感觉老赵的文笔有进步了~

#3楼    回复  引用  查看    

2007-03-08 09:05 by .Live      
比较厉害,,tks

#4楼    回复  引用    

2007-03-08 09:16 by dotneturls [未注册用户]
强帖,谢谢分享!

===========================================
http://***/gb.aspx —.net开发资源精华收集,正在不断更新及完善中,欢迎推荐资源并提出意见和建议!

#5楼    回复  引用    

2007-03-08 09:29 by Woodcode [未注册用户]
学习 强

#6楼    回复  引用  查看    

2007-03-08 10:14 by 极地银狐.NET      
不错,非常有条理啊,PFPF.

#7楼    回复  引用  查看    

2007-03-08 10:31 by webabcd      
这种文章越多越好啊

#8楼    回复  引用    

2007-03-08 11:56 by qq [未注册用户]
<a href=http://www.google.com> link </a>

#9楼    回复  引用  查看    

2007-03-08 14:18 by Leepy      
好啊,强

#10楼 [楼主]   回复  引用  查看    

2007-03-08 14:49 by Jeffrey Zhao      
@命运有自己的梦!
谢谢,以后有问题我们一起讨论一下吧,说不定我会多些灵感。:)

#11楼 [楼主]   回复  引用  查看    

2007-03-08 14:49 by Jeffrey Zhao      
@非我
谢谢鼓励,这一直是我的弱项。

#12楼 [楼主]   回复  引用  查看    

2007-03-08 14:51 by Jeffrey Zhao      
@极地银狐.NET
其实我总是不知该如何去“详细”地剖析实现,因为这总是要涉及到源代码吧,这又该如何写清楚呢?

#13楼 [楼主]   回复  引用  查看    

2007-03-08 14:52 by Jeffrey Zhao      
我在想,什么时候把ASP.NET AJAX的实现从头至尾给详细分析一下……

#14楼    回复  引用    

2007-03-09 06:35 by 怪怪 [未注册用户]
@Jeffrey Zhao
这句话我可逮着了,一直没有时间系统的滤一遍,估计好多人像我一样,这回大家可就等着你了 :P。

P.S. 好文..,干这种理控件脉络事本来是最花时间的,何况Atlas的结合让问题更复杂了,看来老赵现在是轻车熟路了 :)

#15楼    回复  引用    

2007-03-09 06:46 by 怪怪 [未注册用户]
最近感觉两个问题可能大家也考虑过:
一个是异步请求再很多情况下还是得考虑是否是必要的,因为用户对浏览器白了的等待一般都很习惯,而如果无刷新,有的操作等的时间长了,用户就会糊涂,不知道该怎么办。所以如果传输量大,或者服务器端计算时间长,尤其是刷新页面并不影响该操作的流畅度,是不是考虑不用AJAX的方式。

二是javascript真是难,刨除它语言比较宽松、各种实现方式实现各种功能需要注意的问题很多、可查找的资料比较少并且零散等等带来的问题,还难在没思路上。说出来都丢人,比如闭包、特权,我知道它是怎么回事,却不知道它对我有特别大的用处,看文章都说闭包是最强大的特性云云,可我连能够联想到它的需求都产生不了,难道是想象力太有限了?

#16楼    回复  引用    

2007-03-09 06:57 by 怪怪 [未注册用户]
关于一,确实可以给他一个提示,问题是提示也不见得有用。对于我来说,我有时候就希望看见白屏,这告诉我服务器无论什么原因没时间搭理我,我要不耐烦了刷新两下便是,即便还是看不见结果。这个信号虽然混沌,但很明确。可如果给个DIV里面写着在干什么什么让我等,万一时间太长,即使形容的很清楚,我也有点不知道如何是好。如果我还是刷新页面,刷完了较复杂的应用页面状态和刚才就不一样了,对我还好说知道怎么回事,对一般人来说可能反而会感觉困惑然后不耐烦。其实这本来是因为客户端的功能变强了,所以客户端的操作流程和逻辑都增加了。但考虑到Word都没几个人用的好,也许网民数量急剧增加就是因为它操作简单,一个页面连到另一个页面,全都类似于点下一步。

这个也挺痛苦的,对于我来说,总希望能多实现些体现新时代风貌的东西来,可是用户的电脑培训是不是到家呢?我认识的有的IT从业人员,都不爱看过于详细的提示、不爱在一个界面上去寻找和操作需要的功能,最好每一次可操作的有限,然后一步一步地按照他最习惯、比较死的方式走下去就行。要是这样,那还真不如把界面美化元素排除在UpdatePanel外面,然后实现个跟刷新页面差不多的操作方式就完了,不过这样的AJAX程序是不是有点太那个了?

#17楼    回复  引用    

2007-03-09 09:14 by win yee [未注册用户]
一气呵成,痛快。

#18楼 [楼主]   回复  引用  查看    

2007-03-09 09:39 by Jeffrey Zhao      
@怪怪
何谈“轻车熟路”啊,简直差远了,还要在琢磨一下叙述方式。:(

#19楼 [楼主]   回复  引用  查看    

2007-03-09 09:50 by Jeffrey Zhao      
@怪怪
关于第一点,你说的“也许网民数量急剧增加就是因为它操作简单,一个页面连到另一个页面,全都类似于点下一步”可能有点道理。不过AJAX应用的“本意”就是体贴用户(虽然现在可能有写滥用),其中一种手段就是“模拟桌面应用”。其实你说的这个问题就是用户体验方面的问题吧,这需要人来“设计”。还有要做的就是要做好AJAX请求的异常情况,很多人忽略了这一点。

关于第二点,闭包无处不在啊,好处也多多,最常用的Function.createDelegate方法就是闭包的典型范例。其实JavaScript也难吧,如果你在使用时不会在JS问题上受阻碍,那么JS水平应该过关了,赫赫。

#20楼    回复  引用    

2007-03-09 11:03 by LZL [未注册用户]
大家好,我是新手,我想问个问题。我把asp.net ajax 1.0下了,安装在电脑上了,然后打开了ajax项目运行正常,但是我打开website项目,把ScriptManager添加到页面上开始运行就出SYS未定义错误,网上说是web.cfg配置问题,我就根据网上说的配置了,但是打开页面的时候还是出SYS错误。哎,心里难受啊,希望各位帮我解决一下,先谢谢了。....

#21楼 [楼主]   回复  引用  查看    

2007-03-09 11:35 by Jeffrey Zhao      
@LZL
查看浏览器里页面的HTML,您会发现ScriptResource.axd?XXXXX这样的<script />文件引用。直接在浏览器里打开这个文件会看到什么呢?
// 您也可以使用Fiddler查看。

#22楼    回复  引用    

2007-03-09 15:15 by LZL [未注册用户]
我的里面是这内容,麻烦你给我说说具体是什么意思。
</script>


<script src="/WebSite16/WebResource.axd?d=8R2y--aiXia-QnruvqLb6A2&amp;t=633039535301250000" type="text/javascript"></script>


<script src="/WebSite16/ScriptResource.axd?d=Xnn2B7My1C2hGRvcXUtwh7v3bEpx8pbZBjsrgdNkjmW4_BgRzo62fMS6XaN1H7MyfivwLgylydVC2MUUykqdRJr98Zs0emsSfvNlGIDrx481&amp;t=633084442762812500" type="text/javascript"></script>
<script src="/WebSite16/ScriptResource.axd?d=Xnn2B7My1C2hGRvcXUtwh7v3bEpx8pbZBjsrgdNkjmW4_BgRzo62fMS6XaN1H7MyfivwLgylydVC2MUUykqdRIeOg8V2doUGvCb3b-8obEw1&amp;t=633084442762812500" type="text/javascript"></script>
<div>
<script type="text/javascript">
//<![CDATA[
Sys.WebForms.PageRequestManager._initialize('ScriptManager1', document.getElementById('form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);
//]]>
</script>

#23楼    回复  引用    

2007-03-09 15:25 by LZL [未注册用户]
建项目时的web.cfg是这样
<?xml version="1.0"?>
<!--
注意: 除了手动编辑此文件以外,您还可以使用
Web 管理工具来配置应用程序的设置。可以使用 Visual Studio 中的
“网站”->“Asp.Net 配置”选项。
设置和注释的完整列表在
machine.config.comments 中,该文件通常位于
\Windows\Microsoft.Net\Framework\v2.x\Config 中
-->
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<!--
设置 compilation debug="true" 将调试符号插入
已编译的页面中。但由于这会
影响性能,因此只在开发过程中将此值
设置为 true。
-->
<compilation debug="false">
<assemblies>
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></assemblies></compilation>
<!--
通过 <authentication> 节可以配置 ASP.NET 使用的
安全身份验证模式,
以标识传入的用户。
-->
<authentication mode="Windows"/>
<!--
如果在执行请求的过程中出现未处理的错误,
则通过 <customErrors> 节可以配置相应的处理步骤。具体说来,
开发人员通过该节可以配置
要显示的 html 错误页
以代替错误堆栈跟踪。

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
</system.web>
</configuration>

#24楼    回复  引用    

2007-03-09 15:33 by LZL [未注册用户]
帮我看一看缺哪些东西,呵呵,请原谅一个新手的无知

#25楼 [楼主]   回复  引用  查看    

2007-03-09 15:36 by Jeffrey Zhao      
@LZL
引用了几个脚本文件而已。

#26楼 [楼主]   回复  引用  查看    

2007-03-09 15:38 by Jeffrey Zhao      
@LZL
配置文件中缺少了无数的东西……您对比一下运行正常的站点和不正常的站点的配置文件就可以了……

#27楼    回复  引用    

2007-03-09 15:45 by LZL [未注册用户]
请问有没有asp.net ajax的书籍或资料,介绍给我看一看

#28楼    回复  引用    

2007-03-09 16:32 by LZL [未注册用户]
谢谢你了~~~

#29楼    回复  引用    

2007-03-09 20:43 by 怪怪 [未注册用户]
@Jeffrey Zhao
闭包的已有应用还是能了解,可是我自己写代码时,却没怎么利用过这个特性来实现什么东西。我的意思是,这样感觉理解不深,既然文档说是“重要特性”,那么这个重要特性我自己应该能亲自通过利用它,更好的完成自己的构思才是,否则感觉这个知识掌握得很虚...

#30楼 [楼主]   回复  引用  查看    

2007-03-09 21:06 by Jeffrey Zhao      
@怪怪
其实“闭包”从概念到功能上都是“形成一个函数调用的环境”吧,它除了“帮助”函数调用还能做什么呢?而且滥用闭包会让人眼花的。

#31楼    回复  引用    

2007-03-10 02:13 by 怪怪 [未注册用户]
我正是想不清它还能做什么,所以就心虚是不是我自己见识太少了或者脑子不够使呵呵,你也这么说我就不钻牛角尖了 :)

#32楼 [楼主]   回复  引用  查看    

2007-03-10 03:39 by Jeffrey Zhao      
@怪怪
你的想象力和创造力比我高,所以遇到一个问题你首先应该确定,你已经想的比我多了。:)

#33楼    回复  引用    

2007-03-11 16:48 by Ceiba [未注册用户]
赵老师,
我把Ajax从RC换成正式版之后,页面为什么反而刷新的很厉害了呢?

#34楼 [楼主]   回复  引用  查看    

2007-03-11 17:13 by Jeffrey Zhao      
@Ceiba
什么叫做刷新的很厉害呢?

#35楼    回复  引用  查看    

2007-03-12 12:54 by aldebaran      
@Jeffrey Zhao
是"刷新得很厉害"吧,谢谢您的指点,提几点我的看法:
1 在updatePanel中,为什么微软要做!this.ScriptManager.IsInAsyncPostBack判断?为什么不直接this.Initialize();

2 微软是不是应该修改类库,来迎合开发人员写普通的代码就能实现该功能的要求

3 园子里的弟兄是否应该弄个开源项目或是最佳实践的东西,让使用AspnetAjax的人都能很清楚的使用起来.
我想在项目中使用ajax,但这些代码和规范相差如此
之大 ,是很难接受的

#36楼 [楼主]   回复  引用  查看    

2007-03-12 13:05 by Jeffrey Zhao      
@aldebaran
“刷新得很厉害”还是没有看懂在指什么……
1、因为AsyncPostBack之后的UpdatePanel是在ScriptManager的LoadPostData方法里Initialize的(印象中记得是),至于动态添加Trigger出错估计是微软没有考虑到。
2、已经发布了代码,也就不适合修改类库了。而且动态添加Trigger的做法也是比较少数的。ASP.NET AJAX测试了那么长时间都没有反应这个问题,说明它的确很少遇见。
3、这个东西……需要相当的积累才能作吧。想想从C#出现到Effective C#用了3年多吧,其它的例子也是。ASP.NET AJAX的使用还需要沉淀。
// 您说的代码和规范相差如此之大,是指什么呢?什么代码,什么规范呢?

#37楼    回复  引用  查看    

2007-03-13 13:17 by aldebaran      
@Jeffrey Zhao
是相对过于复杂反射的方法代码和公司的表现层代码规范.
不排除有对更复杂的ajax应用,表现层的代码有可能激增.表现层代码的可读性下降

我有这样一个应用场景:
在一个MultiView里有View A和View B,有一个treeView在MultiView外,这样treeView就可以同时出现在两个View;

在View A里需要treeView的onclick 引起 View A 里的GridView异步刷新

在View B里需要 treeView的onclick跳到View A,treeView的回抛是传统的
如果不用动态trigger,想不到其他方法了,请您指教;

我的updatePanel里只有那个GridView

#38楼 [楼主]   回复  引用  查看    

2007-03-13 17:44 by Jeffrey Zhao      
@aldebaran
试试看把TreeView同时作为两个View里的UpdatePanel的Trigger吧。

#39楼    回复  引用  查看    

2007-03-15 16:30 by aldebaran      
@Jeffrey Zhao
不行,它会去找最开始的那个View 的UPdatePanel

#40楼 [楼主]   回复  引用  查看    

2007-03-15 16:36 by Jeffrey Zhao      
@aldebaran
阿哦,使我没有看懂您的意思吗?让我自己试试看。:)

#41楼    回复  引用  查看    

2007-03-21 23:29 by MK2      
我遇到了与他(http://groups.google.com/group/nbeargroup/browse_thread/thread/d415ae237d75c556/c846a71375185070#c846a71375185070)
同样的问题:

在gridview中设置了一个删除按钮,其中的
onclientclick="javascript:return confirm('确定删除吗?');",gridview放在
Updatepanel中,
在IE7.0,点击取消时,并不是预期的结果,而是将结果删除了.


究竟是GridView触发了事件还是删除按钮呢?

#42楼 [楼主]   回复  引用  查看    

2007-03-22 01:07 by Jeffrey Zhao      
@MK2
能不能给我一个最小的可执行的示例呢?我自己尝试了一下,并没有发现什么问题。

#43楼    回复  引用  查看    

2007-03-22 01:59 by MK2      
使用了Northwind数据库, DataSet.xsd提供数据访问层
关键代码:
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Delete" OnClientClick="return confirm('确定删除?');"
Text="删除"></asp:LinkButton>


页面代码:
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="EmployeeID" DataSourceID="ObjectDataSource1">
<Columns>
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Delete" OnClientClick="return confirm('确定删除?');"
Text="删除"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" InsertVisible="False"
ReadOnly="True" SortExpression="EmployeeID" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
</Columns>
</asp:GridView></ContentTemplate>
</asp:UpdatePanel>
</div>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DeleteMethod="Delete" InsertMethod="Insert" OldValuesParameterFormatString="original_{0}" SelectMethod="GetData" TypeName="DataSet1TableAdapters.EmployeesTableAdapter" UpdateMethod="Update">
<DeleteParameters>
<asp:Parameter Name="Original_EmployeeID" Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>


结果是:
即使点击了取消, 也会触发异步回送.
浏览器是IE7.0

#44楼 [楼主]   回复  引用  查看    

2007-03-22 02:17 by Jeffrey Zhao      
@MK2
不好意思,最近事情有些多,您能否发一个可以直接运行的最简单的示例给我看看呢?jeffz[at].live.com。麻烦了。

#45楼    回复  引用    

2007-04-18 09:30 by keyss [未注册用户]
牛人,我感觉你是.net ajax中国软件开发第一人呀,哈哈哈

#46楼 [楼主]   回复  引用  查看    

2007-04-18 13:07 by Jeffrey Zhao      
@keyss
过奖。:)

#47楼    回复  引用    

2007-09-07 17:35 by lqj [未注册用户]
大哥;这个 PostBackTrigger tri = new PostBackTrigger();
tri.ControlID = "DataList1";
UpdatePanel1.Triggers.Add(tri);有没有办法动态添加和删除呢?
比如datalist里面有一个button,当button满足条件的时候需要回传,当button不满足条件的时候就不回传~~~~~~~~谢谢

#48楼 [楼主]   回复  引用  查看    

2007-09-07 23:45 by Jeffrey Zhao      
@lqj
能说得具体一点吗?
button满足什么条件?是客户端的还是服务器端的?回传是指什么啊?

#49楼    回复  引用    

2007-09-10 10:22 by lqj [未注册用户]
imagebutton上面显示普通图片或文件夹图片,如果是普通图片则加载PostBackTrigger tri = new PostBackTrigger();
tri.ControlID = "DataList1";
UpdatePanel1.Triggers.Add(tri);
如果是文件夹图片,则不加载~~~~~~

#50楼    回复  引用    

2008-03-20 01:59 by xwing [未注册用户]
这个问题我也遇到了. 搞了一个晚上,看到你的文章很有收获.非常感谢.

#51楼    回复  引用    

2008-04-15 16:44 by igelf [未注册用户]
解决了,太谢谢了.

#52楼    回复  引用    

2008-04-15 16:55 by igelf [未注册用户]
用第一种方法行.
用反射运行时却弹出错误.
我用的是ToolkitScriptManager

#53楼    回复  引用  查看    

2008-05-08 11:24 by Longkin      
问题严重了,我的是第一次点击按钮页面刷新,数据能够显示出来,而再次点击,就没什么反应了,数据还是第一次点击时的,晕咯!!!
个人觉得是那个按钮根本就没有被添加到那个AsyncPostBackTrigger中去!!
因为我第一次使用时也是如此的。

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-03-12 16:50 编辑过
 
另存  打印