用过Anthem这个AJAX框架的朋友可以直接对一个control通过设置属性来控制在partial postback时设置这个control的Enabled属性为false。AJAX的一个特性就是它暴露XmlHttpRequest的状态,因此很多AJAX框架都提供一种方法来让用户可以针对这个过程来编写一些提高用户体验的代码(当然也有其他功能的,但大多是为了这个目的)。
而Atlas中的postback progress这个过程是由pagerequestmanager类来管理的,它是sealed的,因此我们也就不能按Anthem的思路来解决这个问题了。有时候我们忽视了bindings的作用,在这里我用一个简单的例子来说明如何通过bindings解决这个问题:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="viBlogLogin.aspx.cs" Inherits="viBlogging.viBlogLogin" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>viBlog Login = {fanweixiao}</title>
</head>
<body>
<form id="form1" runat="server">
<atlas:ScriptManager id="sm" runat="server" EnablePartialRendering="true"></atlas:ScriptManager>
<atlas:UpdateProgress ID="upg" runat="server" ><ProgressTemplate>Updating</ProgressTemplate></atlas:UpdateProgress>
<atlas:UpdatePanel ID="testUP" runat="server">
<Triggers>
<atlas:ControlEventTrigger ControlID="btnSubmit" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:Label runat="server" ID="lblShow" />
</ContentTemplate>
</atlas:UpdatePanel>
<asp:TextBox runat="server" ID="tb" Text="Lorem Ipsum" /><br />
<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="btnSubmit_Click" />
</form>
<script type="text/xml-script">
<page>
<components>
<button id="btnSubmit">
<bindings>
<binding dataContext="_PageRequestManager"
dataPath="inPostBack"
property="associatedElement"
propertyKey="disabled"
direction="In"
/>
</bindings>
</button>
</components>
</page>
</script>
</body>
</html>
using
.;
using System.Threading;
using Microsoft.Web.UI;
namespace viBlogging
{
public partial class viBlogLogin : System.Web.UI.Page
{
protected void Page_PreRender(object sender, EventArgs e)
{
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(btnSubmit);
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
lblShow.Text = tb.Text+" fanweixiao";
System.Threading.Thread.Sleep(2000);
}
}
}
实现原理:当程序运行时,有一个PageRequestManager的全局实例(global instance),它在xml-script的<page>里被展现。这个类游一个叫做isPostBack的属性,当页面正在执行postback的时候,isPostback会被设置成true。这个用来控制页面的部分回发(partial postback)和更新页面html内容的PageRequestManager可以告知我们postback的状态了。但是这一切我们都不需要知道它是什么时候发生的,用binding来完成就OK了。
这里有个小问题,UpdatePanel有三种基本的触发模式,在这里,如果把button放到了UpdatePanel里,那么只有第一次点击的时候会被设置成灰色的(enabled=false)。如果使用triggers来指定的话就工作正常,在atlas的官方文档上我没有找到关于说这两种用法有本质不同的地方,希望有知道的朋友告诉一声,thanks in advance ;-)
这是因为如果把Button放到了UpdatePanel并在第一次postback后,control的客户端副本(client couterpart)就会被dispose了,这样就无法实现我们想要的结果了。