如何在 ListView 中群組項目 (HTML)
[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]
了解如何將 ListView 中的項目設為群組。 若要顯示群組資訊 (例如群組標頭和群組界限),您的 ListView 必須使用格線配置。ListView 控制項的 loadingBehavior 屬性必須設為 "randomaccess" (預設值),群組功能才能夠運作。
您必須知道的事
技術
先決條件
- 我們假設您可以建立及使用基本的 ListView 物件。如需 ListView 控制項的簡介,請參閱快速入門:新增 ListView。
指示
步驟 1: 建立您的資料
群組功能需要兩個資料來源:包含項目的 IListDataSource 和包含群組的 IListDataSource。在項目 IListDataSource 中,每個項目都包含一個 groupKey 屬性,以將它連結到群組 IListDataSource 中其所屬的群組。
將新的 JavaScript 檔案新增到專案中,以包含您的資料。將它命名為 "data.js"。
在您剛建立的 data.js 檔案中,建立將提供資料給 ListView 控制項的基礎資料來源。
建立 WinJS.Binding.List 的其中一種方法是建立 IListDataSource。每個 WinJS.Binding.List 都有一個 dataSource 屬性,這個屬性會傳回包含您資料的 IListDataSource。
這個範例會從 JSON 物件陣列 (myData) 建立 WinJS.Binding.List:
// Start of data.js (function () { "use strict"; var myData = [ { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" }, { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" }, { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" }, { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" }, { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" }, { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" }, { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" }, { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" }, { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" }, { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" }, { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" }, { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" }, { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" }, { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" }, { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" }, { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" }, { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" }, { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" }, { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" }, { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" }, { title: "Orangy Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Orangy Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Absolutely Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Absolutely Orange", text: "Sorbet", picture: "images/60Orange.png" }, { title: "Triple Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" }, { title: "Triple Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" }, { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" }, { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" }, { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" }, { title: "Green Mint", text: "Gelato", picture: "images/60Mint.png" } ]; // Create a WinJS.Binding.List from the array. var itemsList = new WinJS.Binding.List(myData);
注意 這個資料會參照數個影像。若要取得影像,請下載 ListView 群組以及 SemanticZoom 範例,然後將影像從範例複製到您的專案。您也可以使用自己的影像 — 只要確定更新資料中的
picture
屬性值即可。秘訣
您不只可以使用 WinJS.Binding.List:您也可以使用自訂的 VirtualizedDataSource。 (StorageDataSource 不支援群組。)如需建立自訂資料來源的詳細資訊,請參閱如何建立自訂資料來源。
建立包含群組資訊的資料來源版本。 如果您使用 WinJS.Binding.List,可以呼叫它的 createGrouped 方法來建立 List 的群組版本。
createGrouped 方法採用 3 個參數:
- getGroupKey:一個函式,假設是清單中的項目,會傳回該項目所屬的群組金鑰。
- getGroupData:一個函式,假設是清單中的項目,會傳回代表該項目所屬群組的資料物件。
- compareGroups:一個用來排序群組的函式,以讓群組 A 優先於群組 B。此函式會取得兩個群組金鑰作為輸入,比較兩個群組,如果第一個群組小於第二個群組,則傳回小於零的值;如果群組相同,則傳回零;如果第一個群組大於第二個群組,則傳回正值。
createGrouped 方法會傳回 WinJS.Binding.List,其中包含來自原始未分組清單的兩個資料投影。投影為動態的,因此如果您要修改清單,請修改原始項目。
這個範例使用 List.createGrouped 方法建立 List 的群組版本。它使用每一個項目標題的第一個字母來定義群組。
// Sorts the groups function compareGroups(leftKey, rightKey) { return leftKey.charCodeAt(0) - rightKey.charCodeAt(0); } // Returns the group key that an item belongs to function getGroupKey(dataItem) { return dataItem.title.toUpperCase().charAt(0); } // Returns the title for a group function getGroupData(dataItem) { return { title: dataItem.title.toUpperCase().charAt(0) }; } // Create the groups for the ListView from the item data and the grouping functions var groupedItemsList = itemsList.createGrouped(getGroupKey, getGroupData, compareGroups);
讓全域範圍都可以存取您的資料。如此一來,當您建立 ListView 時,就能以宣告方式存取資料 (做法請見步驟 2.3)。
這個範例使用 WinJS.Namespace.define,讓群組清單可公開存取。
WinJS.Namespace.define("myData", { groupedItemsList: groupedItemsList }); })(); // End of data.js
步驟 2: 建立使用格線配置的 ListView
接著建立 ListView 並將它與您的資料連接。
在將要包含 ListView 之 HTML 頁面的 head 區段中,新增您在前一步驟所建立之資料檔案的參考。
<!-- Your data file. --> <script src="/js/data.js"></script>
在 HTML 檔案的 body 中,建立 ListView。 將其 layout 屬性設定成 GridLayout。
<div id="groupedListView" data-win-control="WinJS.UI.ListView" data-win-options="{layout: {type: WinJS.UI.GridLayout}}" ></div>
將 ListView 控制項的 itemDataSource 屬性設定為群組項目資料來源。
在步驟 1 中,您建立了包含要顯示之群組項目的命名空間成員:myData.groupedItemsList。呼叫這個欄位會傳回 WinJS.Binding.List。若要取得 ListView 可使用的 IListDataSource,請呼叫其 dataSource 屬性:myData.groupedItemsList.dataSource。
<div id="groupedListView" data-win-control="WinJS.UI.ListView" data-win-options="{itemDataSource: myData.groupedItemsList.dataSource, layout: {type: WinJS.UI.GridLayout}}" ></div>
接著,將 ListView 控制項的 groupDataSource 屬性設為包含群組資料的資料來源。使用 List 物件的 groups 屬性取得包含群組資訊的另一個 List。若要取得 IListDataSource,請呼叫 myData.groupedItemsList.groups.dataSource。
<div id="groupedListView" data-win-control="WinJS.UI.ListView" data-win-options="{itemDataSource: myData.groupedItemsList.dataSource, groupDataSource: myData.groupedItemsList.groups.dataSource, layout: {type: WinJS.UI.GridLayout}}"> </div>
執行應用程式。因為您尚未指定項目範本,所以資料並未格式化:
步驟 3: 建立項目範本和群組標頭範本
在定義 ListView 之前,先在您的 HTML 頁面中建立名為 "mediumListIconTextTemplate" 的 WinJS.UI.Template,並且將 ListView 控制項的 itemTemplate 屬性設定為這個範本的名稱。
<div id="mediumListIconTextTemplate"
data-win-control="WinJS.Binding.Template"
style="display: none">
<div class="mediumListIconTextItem">
<img class="mediumListIconTextItem-Image" data-win-bind="src: picture" />
<div class="mediumListIconTextItem-Detail">
<h4 data-win-bind="innerText: title"></h4>
<h6 data-win-bind="innerText: text"></h6>
</div>
</div>
</div>
<div id="groupedListView"
data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource: myData.groupedItemsList.dataSource,
itemTemplate: select('#mediumListIconTextTemplate'),
groupDataSource: myData.groupedItemsList.groups.dataSource,
layout: {type: WinJS.UI.GridLayout}}">
</div>
(請注意,範本會指定數個樣式。我們稍後將定義這些樣式)。
執行應用程式。項目會格式化,但群組標頭不會格式化。
步驟 4: 建立群組標頭範本
定義群組標頭的 WinJS.UI.Template,並指定 "headerTemplate" 做為其識別碼。將 ListView 控制項的 groupHeaderTemplate 屬性設定為這個範本。
<div id="headerTemplate" data-win-control="WinJS.Binding.Template"
style="display: none">
<div class="simpleHeaderItem">
<h1 data-win-bind="innerText: title"></h1>
</div>
</div>
<div id="mediumListIconTextTemplate"
data-win-control="WinJS.Binding.Template"
style="display: none">
<div class="mediumListIconTextItem">
<img class="mediumListIconTextItem-Image" data-win-bind="src: picture" />
<div class="mediumListIconTextItem-Detail">
<h4 data-win-bind="innerText: title"></h4>
<h6 data-win-bind="innerText: text"></h6>
</div>
</div>
</div>
<div id="groupedListView"
data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource: myData.groupedItemsList.dataSource,
itemTemplate: select('#mediumListIconTextTemplate'),
groupDataSource: myData.groupedItemsList.groups.dataSource,
groupHeaderTemplate: select('#headerTemplate'),
layout: {type: WinJS.UI.GridLayout}}">
</div>
執行應用程式。項目和群組標頭都已格式化。
步驟 5: 設定範本的樣式
如果您要更詳細地指定項目和標頭的外觀,可以用自己的 CSS 樣式設定樣式表。 這個範例中的 CSS 會設定項目和標頭以及 ListView 本身的樣式。
/* CSS for the ListView */
#groupedListView
{
width: 600px;
height: 300px;
border: solid 2px rgba(0, 0, 0, 0.13);
}
/* Template for headers */
.simpleHeaderItem
{
width: 50px;
height: 50px;
padding: 8px;
}
/* Template for items */
.mediumListIconTextItem
{
width: 282px;
height: 70px;
padding: 5px;
overflow: hidden;
display: -ms-grid;
}
.mediumListIconTextItem img.mediumListIconTextItem-Image
{
width: 60px;
height: 60px;
margin: 5px;
-ms-grid-column: 1;
}
.mediumListIconTextItem .mediumListIconTextItem-Detail
{
margin: 5px;
-ms-grid-column: 2;
}
當您執行應用程式時,項目會細分成幾個群組:
您也可以使用 win-groupheader
和 win-container
CSS 類別,來設定群組和項目的樣式。如需詳細資訊,請參閱設定 ListView 及其項目的樣式。
備註
排序和篩選項目與群組
WinJS.Binding.List 可以排序和篩選您的項目與群組。如需詳細資訊,請參閱 createSorted 與 createFiltered 方法。
建立群組的縮小檢視
現在您已了解如何建立群組的 ListView,大致上已能夠使用 SemanticZoom 控制項建立群組的縮小檢視。
如需關於使用 SemanticZoom 的指示,請參閱快速入門:新增 SemanticZoom 控制項。
包含互動標頭的群組 ListView 控制項
當您群組包含互動標頭的 ListView 控制項時,建議您支援 Ctrl+Alt+G 鍵盤快速鍵,並利用它將使用者移入其正在瀏覽的群組。它提供的行為應該要等於按一下或點選群組標頭。
刪除群組和捲動
刪除群組時,ListView 可能會捲動到未預期的位置,所以請呼叫 ensureVisible 方法,捲動到適合應用程式的位置。
完整範例
如需說明如何建立群組 ListView 的完整範例,請參閱 ListView 群組以及 SemanticZoom 範例。