ListView 内の項目をグループ化する方法 (HTML)

[ この記事は、Windows ランタイム アプリを作成する Windows 8.x および Windows Phone 8.x 開発者を対象としています。Windows 10 向けの開発を行っている場合は、「最新のドキュメント」をご覧ください]

ListView で項目をグループ化する方法について説明します。 グループ ヘッダーやグループの境界などのグループ情報を表示するには、ListView でグリッド レイアウトを使う必要があります。グループ機能をすべて利用するには、ListView コントロールの loadingBehavior プロパティを "randomaccess" (既定値) に設定する必要があります。

理解しておく必要があること

テクノロジ

必要条件

手順

ステップ 1: データの作成

グループ化には、項目が含まれる IListDataSource と、グループが含まれる IListDataSource の 2 つのデータ ソースが必要です。項目 IListDataSource 内の各項目に、groupKey プロパティが含まれています。このプロパティによって、グループ IListDataSource 内の各項目が属しているグループに各項目がリンクされています。

  1. データを格納するために、新しい JavaScript ファイルをプロジェクトに追加します。"data.js" という名前を付けます。

  2. 作った data.js ファイルで、ListView コントロールにデータを渡すデータ ソースを作ります。

    IListDataSource を作る 1 つの方法は、WinJS.Binding.List を作ることです。各 WinJS.Binding.ListdataSource プロパティは、データを含む 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 メソッドには、次の 3 つのパラメーターがあります。

    • getGroupKey: 項目がリスト内にある場合に、その項目が属するグループのキーを返す関数です。
    • getGroupData: 項目がリスト内にある場合に、その項目が属するグループを表すデータ オブジェクトを返す関数です。
    • compareGroups: グループ A がグループ B の前になるように、グループを並べ替えるために使われる関数です。2 つのグループを比較して、1 つ目のグループの項目数が 2 つ目のグループの項目数未満の場合は負の値、グループの項目数が等しい場合は 0、1 つ目のグループの項目数が 2 つ目のグループの項目数を超える場合は正の値を返します。

    createGrouped メソッドは、グループ化されていない元の一覧のデータの 2 つのプロジェクションを含む 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 を取得するには、その 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 を定義し、"headerTemplate" という ID を付けます。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

CSS クラスの win-groupheader および win-container を使って、グループと項目のスタイルを指定することもできます。詳しくは、「ListView およびその項目のスタイル指定」をご覧ください。

注釈

項目およびグループの並べ替えとフィルター処理

WinJS.Binding.List は、項目およびグループの並べ替えとフィルター処理を行うことができます。詳しくは、createSorted メソッドと createFiltered メソッドをご覧ください。

グループの縮小表示を作る

ここまでで、グループ化された ListView を作る方法を説明しました。次は、SemanticZoom コントロールを使って、グループの縮小表示を作る方法について説明します。

SemanticZoom コントロールの縮小表示と拡大表示

SemanticZoom の使い方について詳しくは、「クイック スタート: SemanticZoom の追加」をご覧ください。

対話型ヘッダーを含むグループ化された ListView コントロール

グループ化された ListView コントロールに対話型ヘッダーが含まれている場合、キーボード ショートカットの Ctrl + Alt + G をサポートし、ユーザーがそれを使って、現在ナビゲートしているグループに移動できるようにすることをお勧めします。これは、グループ ヘッダー自体をクリックまたはタップした場合と同じ動作を提供します。

グループの削除とスクロール

グループを削除すると、ListView が予期しない位置までスクロールする可能性があるため、アプリにとって適切な位置までスクロールするように ensureVisible メソッドを呼び出します。

完全な例

グループ化された ListView の作成方法を示した例については、ListView のグループ化と SemanticZoom のサンプルのページをご覧ください。

関連トピック

ListView のグループ化と SemanticZoom のサンプルのページ

クイック スタート: SemanticZoom の追加