如何对 ListView 中的项目分组 (HTML)

[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]

学习如何对 ListView 中的项目进行分组。 若要显示组信息(如组标题和组边界),ListView 必须使用网格布局。为了使分组完全正常,ListView 控件的 loadingBehavior 属性必须设置为 "randomaccess"(默认值)。

你需要了解的内容

技术

先决条件

说明

步骤 1: 创建你的数据

分组要求两个数据源:包含项目的 IListDataSource;包含组的 IListDataSource。在项目的 IListDataSource 中,每个项目包含一个 groupKey 属性,该属性将此项链接到它在组 IListDataSource 中所属的组。

  1. 在你的项目中添加新的 JavaScript 文件以包括你的数据。将它命名为 "data.js"。

  2. 在刚创建的 data.js 文件中,创建将为你的 ListView 控件提供数据的基础数据源。

    创建 IListDataSource 的一种方式是创建 WinJS.Binding.List。每个 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 不支持分组。)有关创建自定义数据源的详细信息,请参阅如何创建自定义数据源

     

  3. 创建一个包含分组信息的数据源版本。 如果你使用的是 WinJS.Binding.List,则可以调用它的 createGrouped 方法来创建 List 的分组版本。

    createGrouped 方法采用以下三个参数:

    • 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);
    
  4. 使你的数据可供全局作用域访问。这样,当你创建 ListView 时,可以按照声明方式访问数据(我们将在步骤 2.3 中展示具体做法)。

    此示例使用 WinJS.Namespace.define 使分组的列表可公开访问。

        WinJS.Namespace.define("myData",
            {
                groupedItemsList: groupedItemsList
            }); 
    
    
    })(); // End of data.js
    

步骤 2: 创建一个使用网格布局的 ListView

接着,创建一个 ListView 并将它连接到你的数据。

  1. 在将要包含 ListView 的 HTML 页面的 head 部分中,添加对上一步中创建的数据文件的引用。

    
    
        <!-- Your data file. -->
        <script src="/js/data.js"></script>
    
  2. 在你的 HTML 文件 body 中,创建 ListView。 将其 layout 属性设置为 GridLayout

    
    <div id="groupedListView"
        data-win-control="WinJS.UI.ListView" 
        data-win-options="{layout: {type: WinJS.UI.GridLayout}}"
    ></div>
    
  3. ListView 控件的 itemDataSource 属性设置为分组项目的数据源。

    在步骤 1 中,你创建了一个包含要显示的分组项目的命名空间成员:myData.groupedItemsList。调用此字段会返回一个 WinJS.Binding.List。若要获取可以由 ListView 使用的 IListDataSource,请调用 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>
    
  4. 接下来,将 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>
    

运行该应用。由于你尚未指定项模板,因此数据的格式尚未设置:

显示组原始数据的 ListView。

步骤 3: 创建一个项模板和一个组标题模板

在 HTML 页中,在定义 ListView 之前,创建一个名为 "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>

(请注意,该模板指定多个样式。我们将在以后定义这些样式。)

运行该应用。即可设置项目(而非组标题)的格式。

显示组原始数据的 ListView。

步骤 4: 创建组标题模板

为组标题定义一个 WinJS.UI.Template 并为它赋予一个 ID:"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>

运行该应用。现在可设置项目和组标题的格式。

显示分组数据的 ListView

步骤 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;
    }

当你运行该应用时,你的项目将分成多组:

带有分组项的 ListView

你还可以使用 win-groupheaderwin-container CSS 类来设置你的组和项目的样式。有关详细信息,请参阅设置 ListView 及其项目的样式

备注

对项目和组进行排序和筛选

WinJS.Binding.List 可以对你的项目和组进行排序和筛选。有关详细信息,请参阅 createSortedcreateFiltered 方法。

创建你的组的缩小视图

现在,你知道了如何创建分组的 ListView,你不必太多地了解如何使用 SemanticZoom 控件创建你的组的缩小视图。

SemanticZoom 控件的缩小和放大视图

有关使用 SemanticZoom 的说明,请参阅快速入门:添加 SemanticZoom 控件

包含交互标题的分组 ListView 控件

当你的分组 ListView 控件包含交互标题时,我们建议你启用 Ctrl+Alt+G 键盘快捷键,并使用它将用户移动到他们当前正在导航的组中。它应提供与单击或点击该组标题本身相同的行为。

删除组并滚动

当删除某个组后,ListView 可能会滚动到不需要的位置,所以,可调用 ensureVisible 方法滚动到对你的应用有意义的位置。

完整示例

有关展示如何创建分组 ListView 的完整示例,请参阅 ListView 分组和 SemanticZoom示例。

相关主题

ListView 分组和 SemanticZoom

快速入门:添加 SemanticZoom 控件