Hello World
Spiga

Tip:“Form_Load时添加的AsyncPostBackTrigger失效”问题分析及解决方案

2007-03-08 04:24 by 老赵, 6959 visits

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

问题重现

首先,我们来重现这个问题。新建一张页面,在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文件中输入以下代码:

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生命周期的两个环节中被调用,如下:

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被初始化,如下:

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方法,如下:

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方法了,如下:

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捕捉到的信息,应该如下图所示。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

53 条回复

  1. 命运有自己的梦!
    *.*.*.*
    链接

    命运有自己的梦! 2007-03-08 08:25:00

    我正在为怎样动态的添加异步或者同步的按钮到UpdatePanel感到困惑,想不到看到您的文章后能解决了,先谢了!

  2. 非我
    *.*.*.*
    链接

    非我 2007-03-08 08:51:00

    感觉老赵的文笔有进步了~

  3. .Live
    *.*.*.*
    链接

    .Live 2007-03-08 09:05:00

    比较厉害,,tks

  4. dotneturls[未注册用户]
    *.*.*.*
    链接

    dotneturls[未注册用户] 2007-03-08 09:16:00

    强帖,谢谢分享!

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

  5. Woodcode[未注册用户]
    *.*.*.*
    链接

    Woodcode[未注册用户] 2007-03-08 09:29:00

    学习 强

  6. 极地银狐.NET
    *.*.*.*
    链接

    极地银狐.NET 2007-03-08 10:14:00

    不错,非常有条理啊,PFPF.

  7. webabcd
    *.*.*.*
    链接

    webabcd 2007-03-08 10:31:00

    这种文章越多越好啊

  8. qq[未注册用户]
    *.*.*.*
    链接

    qq[未注册用户] 2007-03-08 11:56:00

    <a href=http://www.google.com> link </a>

  9. Leepy
    *.*.*.*
    链接

    Leepy 2007-03-08 14:18:00

    好啊,强

  10. 老赵
    admin
    链接

    老赵 2007-03-08 14:49:00

    @非我
    谢谢鼓励,这一直是我的弱项。

  11. 老赵
    admin
    链接

    老赵 2007-03-08 14:49:00

    @命运有自己的梦!
    谢谢,以后有问题我们一起讨论一下吧,说不定我会多些灵感。:)

  12. 老赵
    admin
    链接

    老赵 2007-03-08 14:51:00

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

  13. 老赵
    admin
    链接

    老赵 2007-03-08 14:52:00

    我在想,什么时候把ASP.NET AJAX的实现从头至尾给详细分析一下……

  14. 怪怪[未注册用户]
    *.*.*.*
    链接

    怪怪[未注册用户] 2007-03-09 06:35:00

    @Jeffrey Zhao
    这句话我可逮着了,一直没有时间系统的滤一遍,估计好多人像我一样,这回大家可就等着你了 :P。

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

  15. 怪怪[未注册用户]
    *.*.*.*
    链接

    怪怪[未注册用户] 2007-03-09 06:46:00

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

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

  16. 怪怪[未注册用户]
    *.*.*.*
    链接

    怪怪[未注册用户] 2007-03-09 06:57:00

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

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

  17. win yee[未注册用户]
    *.*.*.*
    链接

    win yee[未注册用户] 2007-03-09 09:14:00

    一气呵成,痛快。

  18. 老赵
    admin
    链接

    老赵 2007-03-09 09:39:00

    @怪怪
    何谈“轻车熟路”啊,简直差远了,还要在琢磨一下叙述方式。:(

  19. 老赵
    admin
    链接

    老赵 2007-03-09 09:50:00

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

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

  20. LZL[未注册用户]
    *.*.*.*
    链接

    LZL[未注册用户] 2007-03-09 11:03:00

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

  21. 老赵
    admin
    链接

    老赵 2007-03-09 11:35:00

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

  22. LZL[未注册用户]
    *.*.*.*
    链接

    LZL[未注册用户] 2007-03-09 15:25:00

    建项目时的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>

  23. LZL[未注册用户]
    *.*.*.*
    链接

    LZL[未注册用户] 2007-03-09 15:33:00

    帮我看一看缺哪些东西,呵呵,请原谅一个新手的无知

  24. 老赵
    admin
    链接

    老赵 2007-03-09 15:36:00

    @LZL
    引用了几个脚本文件而已。

  25. 老赵
    admin
    链接

    老赵 2007-03-09 15:38:00

    @LZL
    配置文件中缺少了无数的东西……您对比一下运行正常的站点和不正常的站点的配置文件就可以了……

  26. LZL[未注册用户]
    *.*.*.*
    链接

    LZL[未注册用户] 2007-03-09 15:45:00

    请问有没有asp.net ajax的书籍或资料,介绍给我看一看

  27. LZL[未注册用户]
    *.*.*.*
    链接

    LZL[未注册用户] 2007-03-09 16:32:00

    谢谢你了~~~

  28. 怪怪[未注册用户]
    *.*.*.*
    链接

    怪怪[未注册用户] 2007-03-09 20:43:00

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

  29. 老赵
    admin
    链接

    老赵 2007-03-09 21:06:00

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

  30. 怪怪[未注册用户]
    *.*.*.*
    链接

    怪怪[未注册用户] 2007-03-10 02:13:00

    我正是想不清它还能做什么,所以就心虚是不是我自己见识太少了或者脑子不够使呵呵,你也这么说我就不钻牛角尖了 :)

  31. 老赵
    admin
    链接

    老赵 2007-03-10 03:39:00

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

  32. Ceiba[未注册用户]
    *.*.*.*
    链接

    Ceiba[未注册用户] 2007-03-11 16:48:00

    赵老师,
    我把Ajax从RC换成正式版之后,页面为什么反而刷新的很厉害了呢?

  33. 老赵
    admin
    链接

    老赵 2007-03-11 17:13:00

    @Ceiba
    什么叫做刷新的很厉害呢?

  34. aldebaran
    *.*.*.*
    链接

    aldebaran 2007-03-12 12:54:00

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

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

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

  35. 老赵
    admin
    链接

    老赵 2007-03-12 13:05:00

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

  36. aldebaran
    *.*.*.*
    链接

    aldebaran 2007-03-13 13:17:00

    @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

  37. 老赵
    admin
    链接

    老赵 2007-03-13 17:44:00

    @aldebaran
    试试看把TreeView同时作为两个View里的UpdatePanel的Trigger吧。

  38. aldebaran
    *.*.*.*
    链接

    aldebaran 2007-03-15 16:30:00

    @Jeffrey Zhao
    不行,它会去找最开始的那个View 的UPdatePanel

  39. 老赵
    admin
    链接

    老赵 2007-03-15 16:36:00

    @aldebaran
    阿哦,使我没有看懂您的意思吗?让我自己试试看。:)

  40. MK2
    *.*.*.*
    链接

    MK2 2007-03-21 23:29:00

    我遇到了与他(http://groups.google.com/group/nbeargroup/browse_thread/thread/d415ae237d75c556/c846a71375185070#c846a71375185070)
    同样的问题:

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


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

  41. 老赵
    admin
    链接

    老赵 2007-03-22 01:07:00

    @MK2
    能不能给我一个最小的可执行的示例呢?我自己尝试了一下,并没有发现什么问题。

  42. MK2
    *.*.*.*
    链接

    MK2 2007-03-22 01:59:00

    使用了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

  43. 老赵
    admin
    链接

    老赵 2007-03-22 02:17:00

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

  44. keyss[未注册用户]
    *.*.*.*
    链接

    keyss[未注册用户] 2007-04-18 09:30:00

    牛人,我感觉你是.net ajax中国软件开发第一人呀,哈哈哈

  45. 老赵
    admin
    链接

    老赵 2007-04-18 13:07:00

    @keyss
    过奖。:)

  46. lqj[未注册用户]
    *.*.*.*
    链接

    lqj[未注册用户] 2007-09-07 17:35:00

    大哥;这个 PostBackTrigger tri = new PostBackTrigger();
    tri.ControlID = "DataList1";
    UpdatePanel1.Triggers.Add(tri);有没有办法动态添加和删除呢?
    比如datalist里面有一个button,当button满足条件的时候需要回传,当button不满足条件的时候就不回传~~~~~~~~谢谢

  47. 老赵
    admin
    链接

    老赵 2007-09-07 23:45:00

    @lqj
    能说得具体一点吗?
    button满足什么条件?是客户端的还是服务器端的?回传是指什么啊?

  48. lqj[未注册用户]
    *.*.*.*
    链接

    lqj[未注册用户] 2007-09-10 10:22:00

    imagebutton上面显示普通图片或文件夹图片,如果是普通图片则加载PostBackTrigger tri = new PostBackTrigger();
    tri.ControlID = "DataList1";
    UpdatePanel1.Triggers.Add(tri);
    如果是文件夹图片,则不加载~~~~~~

  49. xwing[未注册用户]
    *.*.*.*
    链接

    xwing[未注册用户] 2008-03-20 01:59:00

    这个问题我也遇到了. 搞了一个晚上,看到你的文章很有收获.非常感谢.

  50. igelf[未注册用户]
    *.*.*.*
    链接

    igelf[未注册用户] 2008-04-15 16:44:00

    解决了,太谢谢了.

  51. igelf[未注册用户]
    *.*.*.*
    链接

    igelf[未注册用户] 2008-04-15 16:55:00

    用第一种方法行.
    用反射运行时却弹出错误.
    我用的是ToolkitScriptManager

  52. Longkin
    *.*.*.*
    链接

    Longkin 2008-05-08 11:24:00

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

  53. Tidks[未注册用户]
    *.*.*.*
    链接

    Tidks[未注册用户] 2008-09-05 09:41:00

    研究这么彻底楼主帮个忙,再研究下UpdatePanel里的FindControl为什么无效?因为Controls集合全部为空,设计期明明有对象的呀。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我