局部更新時如何更新放置在UpdatePanel之外的控制項,本文將提供可能的作法。
UpdatePanel 提供網頁局部更新的功能,讓開發人員可以降低整個網頁回傳到 Server 端所需耗費的等待時間,並避免更新網頁時螢幕閃爍的狀況。由於局部更新的特定,預設只會更新 UpdatePanel 中的控制項內容,在 UpdatePanel 以外的控制項必須在 Server 端使用 ScriptManager.RegisterDataItem 方法,搭配 Client 端 Sys.WebForms.PageRequestManager pageLoading 事件來回應由 Server 端所回傳的資料,才可以在 UpdatePanel 局部更新網頁時也一併更新在 UpdatePanel 外的控制項內容。
假設頁面設計如下,橘色的部分為 UpatePanel ,藍色部分為一般的Div。
程式碼如下:
1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RegisterDataItemDemo.aspx.cs" Inherits="WebApplication5.RegisterDataItemDemo" %>
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: </head>
9: <body>
10: <form id="form1" runat="server">
11: <asp:ScriptManager ID="ScriptManager1" runat="server">
12: </asp:ScriptManager>
13:
14: <asp:UpdatePanel ID="UpdatePanel1" runat="server">
15: <ContentTemplate>
16: <div style="background-color:Orange">
17: <asp:Label ID="Label1" runat="server" Text="我在UpatePanel裡面"></asp:Label>
18: <br />
19: <asp:Label ID="Label2" runat="server" Text="我在UpatePanel裡面"></asp:Label>
20: <br />
21: <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
22: </div>
23: </ContentTemplate>
24: </asp:UpdatePanel>
25: <div style="background-color:Aqua">
26: <asp:Label ID="Label3" runat="server" Text="我在UpatePanel外面"></asp:Label>
27: <br />
28: <asp:Label ID="Label4" runat="server" Text="我在UpatePanel外面"></asp:Label>
29: </div>
30: </form>
31: </body>
32: </html>
筆者在 Button1 的 Click 事件中撰寫下列的程式碼:
1: protected void Button1_Click(object sender, EventArgs e)
2: {
3: Label1.Text = "Label 1:" + DateTime.Now.ToString();
4: Label2.Text = "Label 2:" + DateTime.Now.ToString();
5: }
當使用者按下 Button1 時,不意外地只會更新 Label1和 Label2 (如下圖)。
若要更新位於 UpdatePanel 外面的 Label3 和 Label 4 必須在 Server 端使用 ScriptManager.RegisterDataItem 方法,在局部更新網頁時將資料傳送給控制項。
1: protected void Button1_Click(object sender, EventArgs e)
2: {
3: Label1.Text = "Label 1:" + DateTime.Now.ToString();
4: Label2.Text = "Label 2:" + DateTime.Now.ToString();
5: if (ScriptManager1.IsInAsyncPostBack)
6: {
7: ScriptManager1.RegisterDataItem(Label3, "Label 3:" + DateTime.Now.ToString(), false);
8: JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
9: ScriptManager1.RegisterDataItem(Label4, jsSerializer.Serialize("Label 4:" + DateTime.Now.ToString()), true);
10: }
11: }
上述程式碼第8列宣告一個 System.Web.Script.Serialization 命名空間中的 JavaScriptSerializer 類別 來將要回傳給前端的資料序列化為 JSON 格式,預設為非JSON格式回傳資料。
接著在 aspx 中利用 Sys.WebForms.PageRequestManager pageLoading 事件來回應由 Server 端所回傳的資料,並將結果呈現於 Label3 和 Label4。
1: <script type="text/javascript">
2: Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(PageLoadingHandler);
3: function PageLoadingHandler(sender, args) {
4: var dataItems = args.get_dataItems();
5: if ($get('Label3') !== null)
6: $get('Label3').innerHTML = dataItems['Label3'];
7: if ($get('Label4') !== null)
8: $get('Label4').innerHTML = dataItems['Label4'];
9: }
10: </script>
執行結果如下:
完整程式碼如下:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Web;
5: using System.Web.UI;
6: using System.Web.UI.WebControls;
7: using System.Web.Script.Serialization;
8:
9: namespace WebApplication5
10: {
11: public partial class RegisterDataItemDemo : System.Web.UI.Page
12: {
13: protected void Page_Load(object sender, EventArgs e)
14: {
15:
16: }
17:
18: protected void Button1_Click(object sender, EventArgs e)
19: {
20: Label1.Text = "Label 1:" + DateTime.Now.ToString();
21: Label2.Text = "Label 2:" + DateTime.Now.ToString();
22:
23: if (ScriptManager1.IsInAsyncPostBack)
24: {
25: ScriptManager1.RegisterDataItem(Label3, "Label 3:" + DateTime.Now.ToString(), false);
26: JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
27: ScriptManager1.RegisterDataItem(Label4, jsSerializer.Serialize("Label 4:" + DateTime.Now.ToString()), true);
28: }
29: }
30: }
31: }
【參考資料】