English Version: http://dflying.dflying.net/1/archive/127_paging_your_list_using_aspnet_atlas_pagenavigator_control.html
在這個系列中,我將介紹一些Atlas Sys.UI.Data中較高級的控件,包括:
Sys.UI.Data.List :使用ASP.NET Atlas ListView控制項顯示清單數據
Sys.UI.Data.ItemView:使用ASP.NET Atlas ItemView控制項顯示集合中的單一數據
Sys.UI.Data.DataNavigator:使用ASP.NET Atlas PageNavigator控制項實現客戶端分頁導航
Sys.UI.Data.SortBehavior:待續
Sys.UI.Data.XSLTView:待續這篇是其中的第三篇:使用ASP.NET Atlas PageNavigator控制項實作客戶端分頁導覽把所有的記錄統統放在一個頁面上絕對不是一個好主意,特別是當您有成百上千筆記錄時。您的用戶需要不停的拖曳捲軸,甚至使用Control+F來找到所期待的內容,這將帶來相當差的使用者體驗。這時,將資料以分頁的方式顯示給使用者將友善的多。有些ASP.NET伺服器端控制項擁有內建的分頁及頁面導覽功能,例如DataGrid和GridView。同樣的,Atlas客戶端控制項Sys.UI.Data.DataNavigator也提供了類似的功能,這將大大提高我們的開發效率。
DataNavigator控制項將與DataView(請參考:Atlas命名空間Sys.Data下控制項介紹-DataView和DataFilter )控制項一起運作。我們知道DataView控制項沒有提供頁面導覽相關方法,所以我們只能直接設定它的pageIndex屬性來實現導覽。雖然沒有什麼難度,但很多情況下這並不是一個好辦法,因為像我這樣好多粗心的開發者往往會忘記檢查pageIndex的邊界值,造成不必要的麻煩。這也是Atlas要提供DataNavigator控制項的原因之一,DataNavigator控制項將作為一個DataView控制項的代理(proxy),提供易用的頁面導航介面。
DataNavigator物件只有一個屬性:
dataView:對某個DataView物件的引用,這個DataNavigator將把頁面導覽的操作套用到其上。您應該總是指定這個屬性。
另外,要使用DataNavigator控件,您還需要提供一些擁有一些指定commandName屬性的Atlas Button,以觸發對應的頁面導航操作。這些Button的parent屬性應該設定為此DataNavigator控件,以確保DataNavigator能夠捕獲到這些Button發出的命令。
您可以指定您的Button的commandName屬性為以下五個string,每個都有不同的意義:
page:將目前頁面索引轉換為指令參數(command argument)中指定的值。透過這個指令我們可以快速的改變頁面的索引。
nextpage:切換到下一頁(如果存在下一頁)。
previouspage:切換到上一頁(如果存在上一頁)。
firstpage:切換到第一頁。
lastpage:切換到最後一頁。
OK,MSDN般枯燥的介紹到此為止吧,讓我們透過一個實例來熟悉DataNavigator的使用方法。
首先我們需要揭露一個Web Service,以便Atlas頁面使用。該Web Service將傳回100筆記錄。下面就是這個Web Service的程式碼,非常容易理解,這裡不贅。
Web Service
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Web;
using System.Web.Caching;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services;
//
// For simplicity this example demonstraes storing and manipulating
// the data objects in memory. A database can also be used.
//
[WebService(Namespace = " http://tempuri.org/ ")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MyDataService : DataService
{
static List<Entry> _data;
static object _dataLock = new object();
private static List<Entry> Data
{
get
{
if (_data == null)
{
lock (_dataLock)
{
if (_data == null)
{
_data = new List<Entry>();
for (int i = 0; i < 100; i++)
{
_data.Add(new Entry(i, "Dflying " + i.ToString(), string.Format(" Dflying{0}@dflying.net ", i.ToString())));
}
}
}
}
return _data;
}
}
[DataObjectMethod(DataObjectMethodType.Select)]
public Entry[] SelectRows()
{
return MyDataService.Data.ToArray();
}
}
public class Entry
{
private string _name;
private string _email;
private int _id;
[DataObjectField(true, true)]
public int Id
{
get { return _id; }
設置 { _id = value; }
}
[DataObjectField(false)]
[DefaultValue("New row")]
public string Name
{
get { return _name; }
設置 { _name = 值; }
}
[DataObjectField(false)]
[DefaultValue("")]
public string Email
{
get { return _email; }
設定 { _email = 值; }
}
public Entry()
{
_id = -1;
}
public Entry(int id, string name, string description)
{
_id = id;
_name = name;
_email = description;
}
}
然後,在ASPX頁面中我們需要考慮並定義如下四部分的內容:
一個ScriptManager控件,用來包含頁面必須的Atlas Framework相關腳本檔案。通常情況下,這也是每個Atlas頁面必須包含的。
一個佔位(place holder)的div(id為dataContents,見程式碼)。 Atlas將把渲染後的分頁的ListView放置於此。
一個作為容器的div(DataNavigator控制項),以及其中包含的一組按鈕(指令按鈕),用來實現頁面導航功能。
一個隱藏的div,用來放置ListView的模版。
以下是以上四篇內容的程式碼,關於ListView控制項的模版,請參考我的這篇文章:使用ASP.NET Atlas ListView控制項顯示清單數據
<!-- ScriptManager -->
<atlas:ScriptManager runat="server" ID="scriptManager" />
<!-- Element for paged ListView (container) -->
<div id="dataContents">
</div>
<!-- PageNavigator -->
<div id="pageNavigator">
<input type="button" id="btnFirstPage" value="<<" />
<input type="button" id="btnPrevPage" value="<" />
<span id="lblPageNumber"></span> / <span id="lblPageCount"></span>
<input type="button" id="btnNextPage" value=">" />
<input type="button" id="btnLastPage" value=">>" />
</div>
<!-- Templates -->
<div style="visibility: hidden; display: none">
<table id="myList_layoutTemplate" border="1" cellpadding="3" style="width:20em;">
<thead>
<tr>
<td><span>No.</span></td>
<td><span>Name</span></td>
<td><span>Email</span></td>
</tr>
</thead>
<!-- Repeat Template -->
<tbody id="myList_itemTemplateParent">
<!-- Repeat Item Template -->
<tr id="myList_itemTemplate">
<td><span id="lblIndex" /></td>
<td><span id="lblName" /></td>
<td><span id="lblEmail" /></td>
</tr>
</tbody>
</table>
<!-- Empty Template -->
<div id="myList_emptyTemplate">
No Data
</div>
</div>
最後該書寫Atlas的XML腳本定義了,有以下五個部分:
第一部分:Atlas客戶端控制項DataSource,用來從我們上面定義的Web Service中取得資料。
<dataSource id="dataSource" autoLoad="true" serviceURL="MyDataService.asmx" />
第二部分:一個DataView控制項(請參考:Atlas命名空間Sys.Data下控制項介紹-DataView和DataFilter ),用來將第一部分所取得的那100個資料分頁。
<dataView id="view" pageSize="12">
<bindings>
<binding dataContext="dataSource" dataPath="data" property="data" />
</bindings>
</dataView>
第三部分:一個ListView控制項(請參考: 使用ASP.NET Atlas ListView控制項顯示清單資料),用來顯示分頁好的資料。
<listView id="dataContents" itemTemplateParentElementId="myList_itemTemplateParent" >
<bindings>
<binding dataContext="view" dataPath="filteredData" property="data"/>
</bindings>
<layoutTemplate>
<template layoutElement="myList_layoutTemplate"/>
</layoutTemplate>
<itemTemplate>
<template layoutElement="myList_itemTemplate">
<label id="lblIndex">
<bindings>
<binding dataPath="$index" transform="Add" property="text"/>
</bindings>
</label>
<label id="lblName">
<bindings>
<binding dataPath="Name" property="text"/>
</bindings>
</label>
<label id="lblEmail">
<bindings>
<binding dataPath="Email" property="text"/>
</bindings>
</label>
</template>
</itemTemplate>
<emptyTemplate>
<template layoutElement="myList_emptyTemplate"/>
</emptyTemplate>
</listView>
第四部分: DataNavigator控制項以及指令按鈕。注意到這裡我們有四個按鈕,每一個都有不同的commandName屬性,也分別對應DataNavigator對DataView的一種操作。同時這些按鈕的parent屬性都設定成了這個DataNavigator物件。
<dataNavigator id="pageNavigator" dataView="view"/>
<button id="btnFirstPage" parent="pageNavigator" command="FirstPage" />
<button id="btnPrevPage" parent="pageNavigator" command="PreviousPage">
<bindings>
<binding property="enabled" dataPath="hasPreviousPage"/>
</bindings>
</button>
<button id="btnNextPage" parent="pageNavigator" command="NextPage">
<bindings>
<binding property="enabled" dataPath="hasNextPage"/>
</bindings>
</button>
<button id="btnLastPage" parent="pageNavigator" command="LastPage" />
第五部分:兩個Label,分別顯示頁面總數以及目前頁面的序號。
<label id="lblPageNumber">
<bindings>
<binding dataContext="view" property="text" dataPath="pageIndex" transform="Add"/>
</bindings>
</label>
<label id="lblPageCount">
<bindings>
<binding dataContext="view" property="text" dataPath="pageCount"/>
</bindings>
</label>
OK,在瀏覽器中測試: