本文英文原版与代码下载:
http://aspnet.4guysfromrolla.com/articles/102407-1.aspx
用Microsoft ASP.NET AJAX技术构建交互式的用户界面— Part 2
导言:
在前面部分我们概述了ASP.NET AJAX framework,我们探讨了如何下载和安装该框架,同时对UpdatePanel控件进行了相关概述.把UpdatePanel控件拖动到页面,再把要参与局部回传的控件放置到UpdatePanel控件里,就可以很简单的创建交互式的用户界面.任何由UpdatePanel内的控件触发的回传都会转化为局部页面回传.和整页回传类似,局部回传也向服务器发送一个请求,而不经由客户端脚本.另外,在页面上只有这些区域的编码在HTTP响应里进行返回,且通过JavaScript进行更新.简而言之,局部页面使页面看起来更清爽.客户端和服务器端的代码交互量更少,页面更新更流畅——没有普通回传时常有的闪烁现象.
在Part 1我们考察的UpdatePanel控件实在是太简单了,其仅仅包含了一个Label 和 Button控件.本文,我们将更接近实际的考察UpdatePanel控件,更深入的考察其属性.具体来说,首先我们将在UpdatePanel里使用GridView控件;然后,我们再看一个页面包含多个UpdatePanel控件的情况,阐述UpdatePanel控件的UpdateMode, ChildrenAsTrigger, 以及Triggers属性的功效。
在UpdatePanel里使用GridView控件
使用UpdatePanel控件的好处在于,它可以创建一个具有AJAX功能的用户界面。在现实生活中,用户界面可能会包含数据Web控件,比如GridView。当把它置于UpdatePanel控件时,其所有的功能——比如分页、排序、编辑、删除等可以使用,而不用编写额外的代码等.
本文下载代码里有这样一个实例,一个GridView控件置于UpdatePanel控件里面,其支持编辑、删除、排序、分页等功能.要创建这样的页面,你只需要将ScriptManager 和 UpdatePanel控件添加到页面上;接下来,将一个GridView控件添加到该UpdatePanel控件里。此时,你可以像通常那样对其进行设置,你可以将其绑定到一个公共数据源控件(declarative data source control),并在其智能标签里启用分页、排序、编辑、删除功能。对GridView控件的编辑、删除、分页、排序的彻底阐述超出了本文的范畴,关于这方面的更多详情,请参阅文章
《Working with Data in ASP.NET 2.0》(http://asp.net/learn/data%2Daccess)
完成GridView控件的设置后,在浏览器里进行测试。由于GridView控件放置在 UpdatePanel里,普通情况下将引发整页回传的操作——比如转到下一页面,排序、编辑、删除等,都只会触发局部回传。用户界面看起来清爽多了.
在同一个页面使用多个UpdatePanel控件
到目前为止的2个示例里,我们的页面都只包含一个UpdatePanel控件,其实我们同样可以在页面上使用多个UpdatePanel控件.在某些情况下这很有用,比如页面的不同区域负责不同的操作。打个比方,页面的某个区域供用户输入信息,一旦完成输入后,你可能希望将这些输入信息存入数据库,同时在页面的其它区域将这些输入信息汇总并显示出来.
在默认情况下,页面上的任何一个UpdatePanel控件导致局部回传都会使所有的UpdatePanel控件刷新其界面.我们这样来进行演示,在一个UpdatePanel控件里显示当前的日期和时间.首先创建一个新的ASP.NET页面,并添加一个ScriptManager控件和2个UpdatePanel控件.分别设这2个UpdatePanel控件的ID为UpdatePanel1 和 UpdatePanel2.这它们的ContentTemplates模板里各添加一个Label 和 一个Button控件,同时在这2个UpdatePanel控件的外部再添加另外一个Button按钮,当点击这个外部按钮时,将触发一个整页回传,另外再添加一个Label控件以显示当前的日期和时间。此时,你的页面代码看起来应该和下面的差不多:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label runat="server" id="Panel1Time"></asp:Label>
<br />
<asp:Button runat="server" ID="Panel1Button" Text="Partial Postback from Panel 1" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:Label runat="server" id="Panel2Time"></asp:Label>
<br />
<asp:Button runat="server" ID="Panel2Button" Text="Partial Postback from Panel 2" />
</ContentTemplate>
</asp:UpdatePanel>
<br /><br />
<asp:Label runat="server" id="PageTime"></asp:Label>
<br />
<asp:Button runat="server" ID="FullPostbackButton" Text="Full Postback" />
不管是整页回传还是局部回传,每当登录页面时,都会触发UpdatePanel控件的Load事件。分别为这2个UpdatePanels的Load事件创建事件处理器,在事件处理器里将相应的Label控件的Text属性设置为当前的日期和时间.同样的,在Page_Load事件处理器里对ID为PageTime的Label控件的Text属性进行相应的设置.
protected void Page_Load(object sender, EventArgs e)
{
PageTime.Text = "Page time: " + DateTime.Now.ToString();
}
protected void UpdatePanel1_Load(object sender, EventArgs e)
{
Panel1Time.Text = "UpdatePanel1 time: " + DateTime.Now.ToString();
}
protected void UpdatePanel2_Load(object sender, EventArgs e)
{
Panel2Time.Text = "UpdatePanel2 time: " + DateTime.Now.ToString();
}
在这3个事件处理器里设置断点,并对该页面进行调试。注意在任何时候,当登录该页面时,都会碰到这些断点,不管是第一次登录还是局部回传或整页回传.然而,在某些情况下,只有页面的特定区域才会更新.下面的截屏显示的页面是第一次登录时的情形,请注意这3个Label显示的是相同的日期/时间值.
如果点击"Full Postback" 按钮的话,页面将全部重新呈现,这3个Label控件再次显示相同的日期/时间值.然而,如果点击任意一个"Partial Postback"按钮的话,接着将发生一个局部回传,虽然局部回传依然是对页面按整体进行执行——也就是说仍然会触发这3个Load事件,但页面上只有UpdatePanel控件对其界面进行了更新.
当点击"Partial Postback"按钮后,"Page time" 标签依然显示的是以前的日期/时间值,而UpdatePanel控件里的2个Label显示的是当前的日期/时间值.
图2
有3点需要注意:
1.每次页面登录时都会触发UpdatePanel控件的Load事件,不管页面是局部回传的还是整页回传的(或仅仅是页面第一次登录)
2.当发生局部回传时,UpdatePanel控件外的区域不会发生更新。诚然,页面的Load事件处理器依然被触发了,但用户界面仍然没有更新,这是因为服务器只向UpdatePanel控件的区域返回数据.
3.默认时,触发某个局部回传时,页面上的所有的UpdatePanel控件的界面都会被更新,我们说"默认"是因为可以对该行为进行定制,正如我们后面马上要探讨的那样.
有条件地更新UpdatePanel界面
默认时,当任何一个UpdatePanel控件触发一个局部回传时都会使所有的UpdatePanel控件被刷新。不过我们可以改变这种状况,方法是将UpdatePanel控件的UpdateMode属性设置为Conditional(默认值为Always).一旦你做了修改后,只有在某些情况下该UpdatePanel控件才会刷新。为验证起见,我们使用3个UpdatePanel控件。最上面的控件包含了一个数据输入界面,要求用户输入一个名字,再点击一个指示是敌是友的按钮.接下来是2个UpdatePanel控件,ID分别为FriendPanel 和 FoePanel.其中FriendPanel包含一个GridView控件以列出你输入的友人清单;反之,FoePanel列出的是敌人的清单.
除了用户界面外,每个UpdatePanel控件还包含一个Label控件,在UpdatePanel控件的Load事件处理器里做相应的处理,显示当前的日期和时间。请注意页面顶部的Label控件,在页面的Load事件处理器里用当前的日期和时间值对其Text属性进行赋值.下面的截屏显示的是页面初次登录时的情形,可以看到页面顶部的Label和3个UpdatePanel控件里包含的Label显示的都是相同的时间.该示例的完整代码包含在本文结尾处的下载包里.
默认时,当用户键入名字并点击"This Person is a Friend" 或 "This Person is a Foe"按钮,接着将引发一个局部回传,且所有的UpdatePanels都会进行刷新,然而这样的刷新未免过了头,因为只有FriendsPanel 或 FoePanel需要被刷新(这取决于你点击的是哪个按钮).通过对UpdatePanel控件的刷新进行限制,我们可以减少从服务器返回到浏览器的数据量.
让我们来进行修改,首先将ID为FriendsPanel 和 FoePanel的控件的 UpdateMode属性改为Conditional.这样一来的话,不管是点击"This Person is a Friend" 还是 "This Person is a Foe"按钮都不会对这2个UpdatePanel控件进行更新.我们来验证一下,重新登录该页面,键入一个名字,点击"This Person is a Friend"按钮。这样最上面的UpdatePanel控件将触发一个局部回传,其包含的Label显示的当前的时间,而FriendsPanel 和 FoePanel包含的Label显示的仍然是以前的时间.因为此次的局部回传并没有对这2个UpdatePanel控件进行刷新.
当点击"This Person is a Friend"按钮时我们要告知FriendPanel刷新其界面;同样,当点击 "This Person is a Foe"按钮时我们要告知FoePanel刷新其界面.UpdatePanel的Triggers collection包含了页面上的一系列控件及其相关联的事件,它们都可以促使UpdatePanel控件刷新其界面.在Visual Studio的设计器里,选中UpdatePanel并打开其属性窗口,选择Triggers属性,点击椭圆形区域以打开UpdatePanelTrigger Collection Editor对话框(见下图),在这里你可以指定某个控件或事件在发生局部回传时触发该UpdatePanel刷新其界面.
对FriendPanel而言,将"This Person is a Friend"按钮的Click事件添加为一个AsyncPostbackTrigger;对FoePanel而言,对应的是"This Person is a Foe"按钮.
定义好这些触发器后,重新登录该页面,键入名字,点击"This Person is a Friend"按钮,接着将引发一个局部回传,顶部的那个UpdatePanel以及ID为FriendPanel的UpdatePanel控件都会刷新.然而,FoePanel不会刷新,很明显其包含的Label控件显示的时间并没有改变.
对UpdatePanel控件的补充说明
UpdatePanel控件令人称道的地方在于它可以和绝大多数控件一起工作良好.比如,要使GridView控件具有"AJAX"功能,我们可以将其放置在一个 UpdatePanel控件里,瞧,其编辑、删除、排序、分页功能现在就可以利用AJAX技术来提供一个更具交互性的界面。然而,我们要明白这样一个事实,并不是所有的ASP.NET Web控件都可以和UpdatePanel控件一起搭配起来使用.在微软在文档《UpdatePanel Control Overview》里列出了这些控件,如下:
如下的ASP.NET不支持局部页面更新(partial-page updates),因此,不能放置在UpdatePanel控件里:
.TreeView 和 Menu控件
.Web Parts控件
.FileUpload控件,当在异步回传时,不能用来上载文件.
.GridView 和 DetailsView控件,当它们的EnableSorting 和 PagingCallbacks属性设置为true时不行.不过默认为false.
.Login, PasswordRecovery, ChangePassword,以及CreateUserWizard控件,当其contents没有被转换为editable templates时也不行.
.Substitution控件.
.验证控件,包括 BaseCompareValidator, BaseValidator, CompareValidator, CustomValidator, RangeValidator, RegularExpressionValidator, RequiredFieldValidator,以及 ValidationSummary这些控件.
与局部页面刷新相冲突的这些控件也可以在页面上使用,只不过要放在UpdatePanel控件之外。另外,在某些情况下,我们可以使用特殊的方法使它们支持局部页面刷新。比如,如果你把Login, ChangePassword,或PasswordRecovery控件转换为templates的话,你就可以把它们放置在一个UpdatePanel控件里有关UpdatePanel控件的更多信息,请参阅文章《the UpdatePanel class reference》以及《Introduction to the UpdatePanel control》
展望:
除了ScriptManager 和 UpdatePanel控件外,ASP.NET AJAX Extensions还包含了很多的其它Web控件.我们将在以后的文章考察这些控件并将注意力转移到ASP.NET AJAX Control Toolkit,敬请期待...
祝编程快乐!