这篇博客是我把书上有关动态显示控件和UpdateProgress控件的基本用法结合起来一起使用,实现一个虚拟的当用户点击updatepanel控件中触发Async-Postback动作的控件,或者点击Triggers中所设定的控件而导致updatepanel控件刷新时,若整个刷新动作需耗费较长时间时,我们提供一个进度行或信息,提醒用户目前的状态是正在处理要求中,同时也设计一个取消等待的功能,这样做的好处是:在整个页面呈现停滞状态,使用者虽然仍可以操作网页的其他控件,但是用户极有可能会引发学习记录二中所提到的,遗失前次的Async-Postback刷新动作的问题。
首先我们先来讲解今天例子将要实现的页面效果:这个页面效果是当用户点击一个按钮时,下方会动态的出现一个GridView控件,当选择GridView其中的一行时,textbox中将自动获取这一行的一个字段的值,然后GridView随之消失,在点击行后、textbox获取值前,我们利用线程让获取值的发生时间向后推迟10秒,并且此时,出现一个提示“请等待,勿操作”、一个“取消当前操作”的按钮,如果我们点击“取消当前操作”,textbox将不会获取值,如果没有放弃当前操作,10秒后提示消失,textbox将获取GridView中选择行的字段值。
接着我们来布置网页:
我们新建一个Ajax的web窗体页面重命名为:“updateprogress.aspx”,在页面中拖放一个updatepanel1(16-87行),在updatepanel1中放入一个textbox1(19行)和一个button1(21行),button1的text属性未"…",在textbox前写入"联系方式为:"然后在updatepanel1中再拖放一个updatepanel2(22-81行),在updatepanel2中用自动连接数据源的方式,拖入tb_info表,VS会自动生成一个连接好的表的数据源控件sqldatasource1(47-76行)和绑定好sqldatasource1的GridView1(24-46行,绑定sqldatasource1在27行),选择GridView1中"启动分页"(24行)、"启动选择"功能,将updatepanel1中的ChildrenAsTriggers属性设为False(16行),UpdateMode设为Conditional(17行),然后将updatepanel1的Triggers(83-86行)中的ControlID属性设为GridView1,Eventname设为SelectedIndexChanged,(如果你对我刚才说描述的有关updatamode属性不了解的话,建议你从我的上一篇:Asp.net 中的Ajax学习记录之三:UpdateMode属性及使用UpdateTriggers博客看起,这样更加有助你体会出实例要演示的效果),这个步骤是要完成的效果是,GridView1表是有关求职招聘信息的登记表,当选择到GridView1中任意一行,会引发Updatepanel1的Async-Postback动作,接下来将Updatepanel2控件的UpdateMode(22行)设为Conditional,在Triggers(79行)中加入Button1,Eventname为Click,这个步骤要完成的效果是,当点击Button1,会引发Updatepanel2的Async-Postback动作。
下面我们来学习一下UpdateProgress控件的与Updatepanel控件在页面的结合,我们在Updatepanel1的外面拖放一个UpdateProgress1(88-93行)控件,设定AssociatedUpdatepanelID(88行)属性为Updatepanel1,这个属性的意思是“与UpdateProgress相关联的Updatepanel控件”。(也可以把UpdateProgress控件放到任意的UpdatePanel里面,也可以放到外面。只要他关联的UpdatePanel刷新了,他就会被激活,即使把他放到其他UpdatePanel里面也不例外。)在UpdateProgress1中放入一个label1(90行),text设置为"请等待,勿操作",再放入一个html的Button2(91行)控件value属性设为“取消当前操作”,可能你要问什么选择html控件,我们使用标准控件中的Button可以吗?答案是可以的,但是因为这个Button2不涉及服务器端的事件操作,使用客户端Button控件会更加合理、更优化程序。我们的页面布局好了,下面我们来看一下vs的设计页面中的布局截图,我们对照一下,如下图就是我们想要的效果。
我们再来看一下源代码,对照步骤看行号会更加有助于我们理解控件的属性和值及各种绑定关系:
源代码
1<html xmlns="http://www.w3.org/1999/xhtml">
2<head runat="server">
3 <title>无标题页</title>
4 <script type="text/javascript">
5
6 function pageLoad() {
7 }
8
9 </script>
10</head>
11<body>
12 <form id="form1" runat="server">
13 <div>
14 <asp:ScriptManager ID="ScriptManager1" runat="server" />
15 </div>
16 <asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="False"
17 UpdateMode="Conditional">
18 <ContentTemplate>
19 联系方式为:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
20 <asp:Button ID="Button1" runat="server" Font-Bold="True" Font-Size="Medium"
21 Height="26px" Text="…" />
22 <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
23 <ContentTemplate>
24 <asp:GridView ID="GridView1" runat="server" AllowPaging="True"
25 AutoGenerateColumns="False" BackColor="White" BorderColor="White"
26 BorderStyle="Ridge" BorderWidth="2px" CellPadding="3" CellSpacing="1"
27 DataKeyNames="ID" DataSourceID="SqlDataSource1" EmptyDataText="没有可显示的数据记录。"
28 GridLines="None">
29 <FooterStyle BackColor="#C6C3C6" ForeColor="Black" />
30 <RowStyle BackColor="#DEDFDE" ForeColor="Black" />
31 <Columns>
32 <asp:CommandField ShowSelectButton="True" />
33 <asp:BoundField DataField="type" HeaderText="type" SortExpression="type" />
34 <asp:BoundField DataField="title" HeaderText="title" SortExpression="title" />
35 <asp:BoundField DataField="info" HeaderText="info" SortExpression="info" />
36 <asp:BoundField DataField="linkman" HeaderText="linkman"
37 SortExpression="linkman" />
38 <asp:BoundField DataField="tel" HeaderText="tel" SortExpression="tel" />
39 <asp:CheckBoxField DataField="checkState" HeaderText="checkState"
40 SortExpression="checkState" />
41 <asp:BoundField DataField="date" HeaderText="date" SortExpression="date" />
42 </Columns>
43 <PagerStyle BackColor="#C6C3C6" ForeColor="Black" HorizontalAlign="Right" />
44 <SelectedRowStyle BackColor="#9471DE" Font-Bold="True" ForeColor="White" />
45 <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#E7E7FF" />
46 </asp:GridView>
47 <asp:SqlDataSource ID="SqlDataSource1" runat="server"
48 ConnectionString="<%$ ConnectionStrings:db_SISConnectionString1 %>"
49 DeleteCommand="DELETE FROM [tb_info] WHERE [ID] = @ID"
50 InsertCommand="INSERT INTO [tb_info] ([type], [title], [info], [linkman], [tel], [checkState], [date]) VALUES (@type, @title, @info, @linkman, @tel, @checkState, @date)"
51 ProviderName="<%$ ConnectionStrings:db_SISConnectionString1.ProviderName %>"
52 SelectCommand="SELECT [ID], [type], [title], [info], [linkman], [tel], [checkState], [date] FROM [tb_info]"
53 UpdateCommand="UPDATE [tb_info] SET [type] = @type, [title] = @title, [info] = @info, [linkman] = @linkman, [tel] = @tel, [checkState] = @checkState, [date] = @date WHERE [ID] = @ID">
54 <DeleteParameters>
55 <asp:Parameter Name="ID" Type="Int32" />
56 </DeleteParameters>
57 <InsertParameters>
58 <asp:Parameter Name="type" Type="String" />
59 <asp:Parameter Name="title" Type="String" />
60 <asp:Parameter Name="info" Type="String" />
61 <asp:Parameter Name="linkman" Type="String" />
62 <asp:Parameter Name="tel" Type="String" />
63 <asp:Parameter Name="checkState" Type="Boolean" />
64 <asp:Parameter Name="date" Type="DateTime" />
65 </InsertParameters>
66 <UpdateParameters>
67 <asp:Parameter Name="type" Type="String" />
68 <asp:Parameter Name="title" Type="String" />
69 <asp:Parameter Name="info" Type="String" />
70 <asp:Parameter Name="linkman" Type="String" />
71 <asp:Parameter Name="tel" Type="String" />
72 <asp:Parameter Name="checkState" Type="Boolean" />
73 <asp:Parameter Name="date" Type="DateTime" />
74 <asp:Parameter Name="ID" Type="Int32" />
75 </UpdateParameters>
76 </asp:SqlDataSource>
77 </ContentTemplate>
78 <Triggers>
79 <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
80 </Triggers>
81 </asp:UpdatePanel>
82 </ContentTemplate>
83 <Triggers>
84 <asp:AsyncPostBackTrigger ControlID="GridView1"
85 EventName="SelectedIndexChanged" />
86 </Triggers>
87 </asp:UpdatePanel>
88 <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
89 <ProgressTemplate>
90 <asp:Label ID="Label1" runat="server" Text="请等待,勿操作" Width="150px"></asp:Label>
91 <input ID="Button2" type="button" value="取消当前操作" />
92 </ProgressTemplate>
93 </asp:UpdateProgress>
94 </form>
95</body>
96</html>
97
下面我先来实现当点击Button1时,GridView1出现,选中GridView的任意一行时,联系电话会填充到textbox1中,cs代码如下:
cs代码
1using System.Web.UI.WebControls;
2using System.Web.UI.WebControls.WebParts;
3using System.Xml.Linq;
4
5public partial class UpdateProgress : System.Web.UI.Page
6{
7 protected void Page_Load(object sender, EventArgs e)
8 {
9 if(!this .IsPostBack)
10 GridView1.Visible = false;
11 }
12 //当点击Button1时GridView显示出来,如果已经显示就隐藏
13 protected void Button1_Click(object sender, EventArgs e)
14 {
15 if (!GridView1.Visible)
16 GridView1.Visible = true;
17 else
18 GridView1.Visible = false;
19 }
20 //当GridView选中行时,textbox的值为选中行的第6个单元格的值,然后GridView再次隐藏
21 protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
22 {
23 TextBox1.Text = GridView1.SelectedRow.Cells[5].Text.ToString();
24 GridView1.Visible = false;
25 }
26}
效果图如下:
接下来我们来实现用线程停止10秒,显示提示功能是效果,cs代码如下:
等待10秒的cs代码
1 //当GridView选中行时,textbox的值为选中行的第6个单元格的值,然后GridView再次隐藏
2 protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
3 { //选中后等待10秒,10秒后再获取值
4 System.Threading.Thread.Sleep(10000);
5 TextBox1.Text = GridView1.SelectedRow.Cells[5].Text.ToString();
6 GridView1.Visible = false;
7 }
下面我再次运行,当我们还是点击第3行时,因为等待10秒后才完成Async-Postback动作,对使用者来说,在点击Button按钮后,网页就会呈现停滞状态,UpdateProgress控件就会显示出来,当Async-Postback动作完成后,这个信息就会自动消失,页面截图如下:
下面我们来实现取消当前操作的用法,这种取消操作是Async-Postback动作发生前在客户端发生的,因此我们要编写JavaScript脚本,由于本人对js的功底较弱,下面的客户端js代码是书中的原作,源代码如下:
加入取消操作后的源代码
1<%@ Page Language="C#" AutoEventWireup="true" CodeFile="UpdateProgress.aspx.cs" Inherits="UpdateProgress" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5<html xmlns="http://www.w3.org/1999/xhtml">
6<head runat="server">
7 <title>无标题页</title>
8 <script type="text/javascript">
9
10 function pageLoad() {
11 }
12
13 </script>
14</head>
15<body>
16 <form id="form1" runat="server">
17 <div>
18 <asp:ScriptManager ID="ScriptManager1" runat="server" />
19 <script language ="javascript" >
20 //取得PageRequestManager对象,每一个Asp.net Ajax页面中会右唯一一个这种对象负责处理所有的Async-Postback要求
21 var prm=Sys .WebForms .PageRequestManager.getInstance();
22 //新增事件处理至PageRequestManager的initializeRequest事件,当Async-Postback发生时,此事件会被触发,我们的InitRequest函数便会被运行
23 prm.add_initializeRequest(InitRequest);
24 //新增事件处理至PageRequestManager的endRequest事件,当Async-Postback完成时,此事件会被触发,我们的EndRequest函数便会被运行
25 prm.add_endRequest(EndRequest);
26 function InitRequest(sender,args)
27 {
28 //显示出UpdateProgress1控件
29 document .getElementById ("UpdateProgress1").style.display="block";
30 }
31 function EndRequest(sender,args)
32 {
33 //隐藏UpdateProgress1控件
34 document .getElementById ("UpdateProgress1").style.display="none";
35 }
36 //用于取消Async-Postback动作
37 function CancelClick()
38 {
39 //当处于Async-Postback动作时,get_isInAsyncPostBack函数会回传true,此时调用abortPostBack 函数便会取消Async-Postback动作。
40 if(prm.get_isInAsyncPostBack())
41 {
42 prm.abortPostBack ();
43 }
44
45 }
46
47 </script>
48 </div>
49 <asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="False"
50 UpdateMode="Conditional">
51 <ContentTemplate>
52 联系方式为:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
53 <asp:Button ID="Button1" runat="server" Font-Bold="True" Font-Size="Medium"
54 Height="26px" onclick="Button1_Click" Text="…" />
55 <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
56 <ContentTemplate>
57 <asp:GridView ID="GridView1" runat="server" AllowPaging="True"
58 AutoGenerateColumns="False" BackColor="White" BorderColor="White"
59 BorderStyle="Ridge" BorderWidth="2px" CellPadding="3" CellSpacing="1"
60 DataKeyNames="ID" DataSourceID="SqlDataSource1" EmptyDataText="没有可显示的数据记录。"
61 GridLines="None" onselectedindexchanged="GridView1_SelectedIndexChanged">
62 <FooterStyle BackColor="#C6C3C6" ForeColor="Black" />
63 <RowStyle BackColor="#DEDFDE" ForeColor="Black" />
64 <Columns>
65 <asp:CommandField ShowSelectButton="True" />
66 <asp:BoundField DataField="type" HeaderText="type" SortExpression="type" />
67 <asp:BoundField DataField="title" HeaderText="title" SortExpression="title" />
68 <asp:BoundField DataField="info" HeaderText="info" SortExpression="info" />
69 <asp:BoundField DataField="linkman" HeaderText="linkman"
70 SortExpression="linkman" />
71 <asp:BoundField DataField="tel" HeaderText="tel" SortExpression="tel" />
72 <asp:CheckBoxField DataField="checkState" HeaderText="checkState"
73 SortExpression="checkState" />
74 <asp:BoundField DataField="date" HeaderText="date" SortExpression="date" />
75 </Columns>
76 <PagerStyle BackColor="#C6C3C6" ForeColor="Black" HorizontalAlign="Right" />
77 <SelectedRowStyle BackColor="#9471DE" Font-Bold="True" ForeColor="White" />
78 <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#E7E7FF" />
79 </asp:GridView>
80 <asp:SqlDataSource ID="SqlDataSource1" runat="server"
81 ConnectionString="<%$ ConnectionStrings:db_SISConnectionString1 %>"
82 DeleteCommand="DELETE FROM [tb_info] WHERE [ID] = @ID"
83 InsertCommand="INSERT INTO [tb_info] ([type], [title], [info], [linkman], [tel], [checkState], [date]) VALUES (@type, @title, @info, @linkman, @tel, @checkState, @date)"
84 ProviderName="<%$ ConnectionStrings:db_SISConnectionString1.ProviderName %>"
85 SelectCommand="SELECT [ID], [type], [title], [info], [linkman], [tel], [checkState], [date] FROM [tb_info]"
86 UpdateCommand="UPDATE [tb_info] SET [type] = @type, [title] = @title, [info] = @info, [linkman] = @linkman, [tel] = @tel, [checkState] = @checkState, [date] = @date WHERE [ID] = @ID">
87 <DeleteParameters>
88 <asp:Parameter Name="ID" Type="Int32" />
89 </DeleteParameters>
90 <InsertParameters>
91 <asp:Parameter Name="type" Type="String" />
92 <asp:Parameter Name="title" Type="String" />
93 <asp:Parameter Name="info" Type="String" />
94 <asp:Parameter Name="linkman" Type="String" />
95 <asp:Parameter Name="tel" Type="String" />
96 <asp:Parameter Name="checkState" Type="Boolean" />
97 <asp:Parameter Name="date" Type="DateTime" />
98 </InsertParameters>
99 <UpdateParameters>
100 <asp:Parameter Name="type" Type="String" />
101 <asp:Parameter Name="title" Type="String" />
102 <asp:Parameter Name="info" Type="String" />
103 <asp:Parameter Name="linkman" Type="String" />
104 <asp:Parameter Name="tel" Type="String" />
105 <asp:Parameter Name="checkState" Type="Boolean" />
106 <asp:Parameter Name="date" Type="DateTime" />
107 <asp:Parameter Name="ID" Type="Int32" />
108 </UpdateParameters>
109 </asp:SqlDataSource>
110 </ContentTemplate>
111 <Triggers>
112 <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
113 </Triggers>
114 </asp:UpdatePanel>
115 </ContentTemplate>
116 <Triggers>
117 <asp:AsyncPostBackTrigger ControlID="GridView1"
118 EventName="SelectedIndexChanged" />
119 </Triggers>
120 </asp:UpdatePanel>
121 <asp:UpdateProgress ID="UpdateProgress1" runat="server"
122 AssociatedUpdatePanelID="UpdatePanel1">
123 <ProgressTemplate>
124 <asp:Label ID="Label1" runat="server" Text="请等待,勿操作" Width="150px"></asp:Label>
125 <input ID="Button2" type="button" value="取消当前操作" onclick="CancelClick()" />
126 </ProgressTemplate>
127 </asp:UpdateProgress>
128 </form>
129</body>
130</html>
131
默认情况下UpdateProgress控件的内容是以隐藏的<div>标签显示,在没显示之前他并不占用页面上的空间,比如ID为upg的控件,他呈现的代码会是:<div id="upg" style="display:none;">(如34行).....</div>。但是如果将他的DynamicLayout属性设为false,他将会在页面上占据一定的空间,此时他呈现的代码会是:<div id="upg" style="visibility:hidden;display:block;">(如29行)</div>。新增的19-47行的JavaScript代码注释写的很详细,大家可以看看一下,前几天我见过vs2010的预览版,其中一个很大的进步就是在写js代码时也会出现像写.net程序时的语法提示,这样大大方便了像我这样可以通过提示自学只用js的人群,太便利了。
再次运行代码就会出现当点击取消时,UpdateProgress1就会消失,同时10秒后也不会获取联系方式,但是如果你动手做这个例子就会发现有个现象,就是只要我们点击Button1时,UpdateProgress1也会闪一下,这是因为Button1在单击的时候引发了Updatepanel2的Async-Postback方法,所以UpdateProgress1用根据上面代码中的第23 行发生显示UpdateProgress1的函数。我们还要注意的一点是:如果一个UpdatePanel(A)嵌套在另一个UpdatePanel(B)里面,此时如果A刷新了,则关联B的UpdateProgress也会被激活。即子UpatePanel刷新了,关联父UpdatePanel的UpdateProgress也会被激活。其实调用abortpostback函数的用意是放弃Async-Postback时的刷新Updatepanel1控件动作,对于服务器端来说,整个Async-Postback动作还是会运行完,所以用取消这个字眼其实并不太正确,应该说是放弃Async-Postback后的刷新动作较为贴切。