かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

WinJSでコレクションのバインド

以下の内容を試した感じです。

コレクションの基本的なバインド方法

WinJSでバインド可能なオブジェクトの定義はいろんな方法があるみたいで、上記のリンクではWinJS.Binding.define関数が使われてました。これはオブジェクトを渡してやると、そのプロパティをもったクラスを返すみたいな関数みたいです。

これを使ってnameとageを持ったPersonクラスを定義します。そして、表示用の配列を用意します。

// nameとageを持ったバインド可能なPersonの定義
var Person = WinJS.Binding.define({
    name: "",
    age: 0
});

// Personの配列
var people = [
    new Person({ name: "tanaka1", age: 10 }),
    new Person({ name: "tanaka2", age: 20 }),
    new Person({ name: "tanaka3", age: 30 }),
    new Person({ name: "tanaka4", age: 40 }),
    new Person({ name: "tanaka5", age: 50 }),
    new Person({ name: "tanaka6", age: 60 })
];

テンプレートの定義

テンプレートはWinJS.Binding.Templateをdata-win-control属性に指定したdivタグで定義します。とりあえず、body直下に以下のようなulにnameとageをバインドするようなテンプレートを定義しました。

<!-- テンプレート -->
<div id="templateDiv" data-win-control="WinJS.Binding.Template">
    <ul>
        <li class="win-type-medium">名前:<span data-win-bind="textContent: name"></span></li>
        <li class="win-type-medium">年齢:<span data-win-bind="textContent: age"></span></li>
    </ul>
</div>

レンダリングのターゲットの用意

データをレンダリングするためのプレイスホルダを定義します。これもただのdivタグです。

<div id="container">
    <!-- レンダリングターゲット -->
    <div id="renderTarget"></div>
</div>

レンダリング処理

WinJSのwinControlプロパティとかに触るためにWinJS.UI.processAllが完了したあとに、テンプレートのwinControl.renderメソッドを呼び出します。レンダリングするオブジェクトと、レンダリングする場所を渡してやる感じです。先ほどの配列をレンダリングする場合は以下のようになります。

// processAllの後にコントロールの初期化
WinJS.UI.processAll().then(function () {
    // テンプレートの要素を取得
    var templateElement = document.querySelector("#templateDiv");
    // レンダリングのターゲットの取得
    var renderTarget = document.querySelector("#renderTarget");

    // テンプレートを使ってターゲットに要素をバインドする
    people.forEach(function (item) {
        templateElement.winControl.render(item, renderTarget);
    });
});;

コード全体

HTMLとJavaScriptの全体は以下のようになってます。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>WinJS Hello world</title>
    <link href="WinJS/css/ui-dark.css" rel="stylesheet" />
    <script src="WinJS/js/base.js"></script>
    <script src="WinJS/js/ui.js"></script>
    <script src="WinJS/js/WinJS.js"></script>
    <script type="text/javascript">
        (function () {
            "use strict";

            WinJS.Application.onready = function () {
                // nameとageを持ったバインド可能なPersonの定義
                var Person = WinJS.Binding.define({
                    name: "",
                    age: 0
                });

                // Personの配列
                var people = [
                    new Person({ name: "tanaka1", age: 10 }),
                    new Person({ name: "tanaka2", age: 20 }),
                    new Person({ name: "tanaka3", age: 30 }),
                    new Person({ name: "tanaka4", age: 40 }),
                    new Person({ name: "tanaka5", age: 50 }),
                    new Person({ name: "tanaka6", age: 60 })
                ];

                // processAllの後にコントロールの初期化
                WinJS.UI.processAll().then(function () {
                    // テンプレートの要素を取得
                    var templateElement = document.querySelector("#templateDiv");
                    // レンダリングのターゲットの取得
                    var renderTarget = document.querySelector("#renderTarget");

                    // テンプレートを使ってターゲットに要素をバインドする
                    people.forEach(function (item) {
                        templateElement.winControl.render(item, renderTarget);
                    });
                });;
            };
            WinJS.Application.start();
        })();
    </script>
    <style type="text/css">
        #container {
            margin: 10px;
        }
    </style>
</head>
<body>
    <!-- テンプレート -->
    <div id="templateDiv" data-win-control="WinJS.Binding.Template">
        <ul>
            <li class="win-type-medium">名前:<span data-win-bind="textContent: name"></span></li>
            <li class="win-type-medium">年齢:<span data-win-bind="textContent: age"></span></li>
        </ul>
    </div>

    <div id="container">
        <!-- レンダリングターゲット -->
        <div id="renderTarget"></div>
    </div>

</body>
</html>

実行結果

実行すると、以下のようになります。

f:id:okazuki:20141229225916p:plain