かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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