續前一篇文章「讓 ASP.NET AJAX 支援瀏覽器的 History Navigation - Part 1」,之前介紹的是用 History 控制項的做法,雖然可適用 ASP.NET 2.0 及之後所有 .NET 版本的網頁,但必須多經一次安裝 Future 套件,或多做一次引用 Microsoft.Web.Preview.dll 的動作,畢竟較不方便。本帖介紹的是 ASP.NET 3.5 SP1 / VS 2008 SP1 的做法,直接引用已經內建在新版 ScriptManager 控制項內的 History Navigation 功能,達成和上一篇文章相同的效果。
如 Dino Esposito 在這篇文章所說的:
http://dotnetslackers.com/articles/aspnet/AFirstLookAtASPNETExtensions35HistoryPoints.aspx
在已安裝 VS 2008 SP1 的網站裡 (等同已安裝 .NET 3.5 SP1),先啟用 ScriptManager 內建的 History Navigation 功能,並建立 ScriptManager1_Navigate 事件處理函數,如下:
ScriptManager
<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="true"
onnavigate="ScriptManager1_Navigate">
</asp:ScriptManager>
之後只要使用者在 URL 網址中做 Navigate 時 (如本帖下載樣本中,在 UpdatePanel 中的 GridView 按頁碼換頁後,再按瀏覽器的「上一頁」時),就會觸發此一事件。
ScriptManager..::.Navigate Event:
Occurs when the user clicks the browser's Back or Forward button.
接下來,程式員就要在 Code-Behind 中撰碼,在適當時機加入 History Point。以本帖下載樣本而言,就是在 GridView1_PageIndexChanged 事件處理函數中,撰碼加入 History Point。此後,當使用者在做 URL Navigate 時,例如像本例中,單擊 GridView 的頁碼換頁時,新版的 ScriptManager 控制項就會在 URL 網址後面,加上一串看似亂碼的 user state。如本帖的前一篇文章所提過的,這串瀏覽器的 navigating 曆程資訊,會經過「序列化 (serialization)」並加密後,再附加在 URL 網址後方,以供瀏覽器作為辨識之用。
----------------------------------------
本帖的 ASP.NET 3.5 + SP1 範例程式碼下載點:
http://files.cnblogs.com/WizardWu/081005.zip
(執行本樣本,需要 VS 2008 SP1 + SQL Server 的 Northwind 資料庫)
----------------------------------------
這個樣本和傳統的 AJAX + GridView 網頁,有幾個不同點:
1、當 GridView 換頁時,IE (或 Firefox) 左上方的「上一頁、下一頁」按鈕會自動啟用;若為傳統的 AJAX 網頁則不會。
2、假設您換頁到 GridView 的第二頁 (或其它任何一頁),此時若再進到別的頁面,再按瀏覽器左上方的「上一頁」回來時,GridView 仍會停在第二頁;若為傳統的 AJAX 網頁則不然,而是一律跳回 GridView 的第一頁。
3、當 GridView 換頁後,此時若將該頁加入瀏覽器的「書籤 (bookmark)」,會一併記錄是在 GridView 的哪一頁;若為傳統的 AJAX 網頁則不會記錄。
4、搭配 FormView、DetailsView 控制項使用時,在改變這兩個控制項的狀態時 (Insert、Edit、ReadOnly mode),亦能記錄頁數和 state (這點版工我未測試成功)。
5、搭配 ASP.NET 的 Wizard 控制項使用時,亦能記錄頁數和 state (這是 Dino 講的,這點版工我未試過)。
Default.aspx
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="true"
onnavigate="ScriptManager1_Navigate">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server" AllowPaging="True"
AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="OrderID"
DataSourceID="SqlDataSource1" onpageindexchanged="GridView1_PageIndexChanged">
<Columns>
<asp:BoundField DataField="OrderID" HeaderText="OrderID" InsertVisible="False"
ReadOnly="True" SortExpression="OrderID" />
<asp:BoundField DataField="CustomerID" HeaderText="CustomerID"
SortExpression="CustomerID" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [OrderID], [CustomerID] FROM [Orders]">
</asp:SqlDataSource>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
private static string pageKey = "p";
protected void Page_Load(object sender, EventArgs e)
{ }
protected void ScriptManager1_Navigate(object sender, HistoryEventArgs e)
{
if (e.State.Count <= 0)
{
// Setup default state
GridView1.PageIndex = 0;
return;
}
string key = e.State.AllKeys[0];
string state = String.Empty;
if (String.Equals(key, pageKey))
{
state = e.State[key];
int pageIndex = Int32.Parse(state
GridView1.PageIndex = pageIndex;
}
}
protected void GridView1_PageIndexChanged(object sender, EventArgs e)
{
string state = (sender as GridView).PageIndex.ToString();
ScriptManager.GetCurrent(this).AddHistoryPoint(pageKey, state);
}
}
---------------------------------------------------------------------------------
參考檔案:
[1] MSDN Library, 「ScriptManager.Navigate Event (System.Web.UI)」:
http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.navigate.aspx
[2] MSDN Library, 「ScriptManager..::.AddHistoryPoint Method 」:
http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.addhistorypoint.aspx
[3] Dino Esposito, 「A First Look at ASP.NET Extensions 3.5—History Points」:
http://dotnetslackers.com/articles/aspnet/AFirstLookAtASPNETExtensions35HistoryPoints.aspx