WinJS2.1 によるテンプレートを使用したデータバインド
いくら検索しても見つけられなかった Visual Studio 2013 のショートカットキー一覧を、US 出張の際に「紙」で もらいました。メモ代わりに内容をこのブログに載せようと思い、念のためもういちど Web を検索してみたら、すんなりと記事が見つかってしまいモンヤリしている秋のはじまり、皆様、いかがお過ごしでしょうか?
Visual Studio のヒントとテクニック
https://msdn.microsoft.com/ja-jp/library/dn320181.aspx
今回の記事では、Visual Studio とはまったく関係なく、Web ブラウザーからも使用できるようになった、WinJS2.1 が提供するテンプレートの機能を使用したデータバインドの方法について紹介したいと思います。
なお、データバインドがよくわからないという方は、あらかじめ以下の記事をお読みいただくとこれからの記事について理解が深まることでしょう。
Web ブラウザーから使う、WinJS2.1 入門(データバインド)
https://blogs.msdn.com/b/osamum/archive/2014/07/28/winjs2-1databind.aspx
テンプレートとは?
「Template 」(テンプレート)とは、日本語ではひな形、鋳型、型板を意味し、そこに材料を流し込むなり、それの形を複製し、土台としてなにかを作成するのに使用します。
HTML + JavaScript のプログラミングにおけるテンプレートも同様です。具体的には、非表示にした、定型化された HTML エレメントの集合を複製し、データを流し込んで表示を行います。
テンプレートの処理にデータバインドを組み合わせると、各項目へのデータの設定や、件数の変化にも自動で対応されるようになるため作業効率が高まります。
WinJS の提供するテンプレート機能
WinJS では、テンプレートを WinJS.Binding.Template オブジェクトとして提供しており、JavaScript からもマークアップからも使用することができます。
WinJS のテンプレートは、ListViewオブジェクトや FlipView オブジェクトと共に使ってオブジェクトをリストアイテムとして表示することができます。
コードで記述した場合
var object = new WinJS.Binding.Template(element, options);
マークアップで記述した場合
<div id="templateDiv" data-win-control="WinJS.Binding.Template"></div>
ここでは一般的に使用されることの多いマークアップでの使用方法について紹介します。
テンプレートを使用した ListView コントロールの表示
ListView コントロールは、リストのアイテムの表示にテンプレートを使用します。
ここではテンプレートを使用した ListView の表示方法について紹介します。
準備
HTML に以下のように WinJS2.1 のライブラリとスタイルシートを参照させます。
<link href="Microsoft.WinJS.2.1/css/ui-light.css" rel="stylesheet" />
< script src="Microsoft.WinJS.2.1/js/base.js"></script>
< script src="Microsoft.WinJS.2.1/js/ui.js"></script>
ListView に表示するためのデータを script タグ内に用意します。データは以下のようなオブジェクトの配列です。
var dataArray = [
{ title: "りんご", text: "リンゴ(林檎、学名:Malus pumila)", picture: "img/apple.png" },
{ title: "オレンジ", text: "甘橙(学名:Citrus sinensis)", picture: "img/orange.png" },
{ title: "マンゴー", text: "(檬果、芒果、学名:Mangifera indica)", picture: "img/mango.png" },
{ title: "バナナ", text: "(甘蕉、実芭蕉、学名 Musa spp. )", picture: "img/banana.png" }
];
テンプレートと ListView コントロールの記述
アイテム (レコード) の各項目 (フィールド) の内容を表示するためのコントロールと、コントロールの data-win-bid アトリビュート内に、データを流し込むコントロールのプロパティと、そこに紐づけるデータのプロパティ名を記述します。詳しくは「Web ブラウザーから使う、WinJS2.1 入門(データバインド)」の内容を参照してください。記述する箇所は非表示となるためどこでも良いですが、body タグの直下などによく書かれるようです。
<!-- テンプレートの定義-->
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template">
<div id="listItem" >
<!-- "picture" フィールドを表示 -->
<img id="productImg" data-win-bind="alt: title; src: picture" src="#" />
<div id="description">
<!-- "title" フィールドを表示 -->
< h4 data-win-bind="innerText: title"></h4>
<!-- "text" フィールドを表示 -->
< h6 data-win-bind="innerText: text"></h6>
</div>
</div>
</div>
リストを表示するための ListView のタグを記述します。
<!—ListView の定義 -->
<div id="listView" data-win-control="WinJS.UI.ListView"
data-win-options="{
itemDataSource:DataExample.itemList.dataSource,
itemTemplate:select('#mediumListIconTextTemplate'),
layout:{type:WinJS.UI.GridLayout}
}"></div>
< /div>
data-win-options 属性の中がかなり複雑なことになっていますが、これは設定に必要な ListView のプロパティをすべて data-win-options 属性の中で設定しているからです。JavaScript 側でプロパティを設定すればもっとすっきりとした記述になります。(その方法はあとで紹介します)
ListView コントロールを表示するための CSS を定義します。
#listItem { width:300px; }
#productImg {
height:50px;
width:50px;
margin:5px;
display:-ms-flexbox;
display:-webkit-flex;
}
#description {
margin:5px;
display:-ms-flexbox;
display:-webkit-flex;
}
#listView {
width:1000px;
height:500px;
}
データとコントロールの接続
前述した script タグの中に記述したオブジェクト配列を ListView にセットするためのバインドリストを生成し、マークアップ (DOM) のアトリビュート内からアクセス可能とするためにネームスペースにバインドリストを登録します。
//オブジェクトの配列からバインディングリストを生成
var itemList = new WinJS.Binding.List(dataArray);
//マークアップ内からアクセス可能とするためネームスペースを
//生成してバインドリストを登録
var publicMembers ={
itemList: itemList
};
WinJS.Namespace.define("DataExample", publicMembers);
WinJS のコントロールを表示するためのメソッドを実行します。この処理についての詳細は「Web ブラウザーから使う、WinJS2.1 入門(導入とコントロールの配置)」を参照してください。
//WinJS コントロールを表示すめための処理
document.addEventListener("DOMContentLoaded", function () {
WinJS.UI.processAll();
});
実行結果
実行すると、以下のようなリストビューが表示されます。
HTML 全体の内容は以下のとおりです。
<!DOCTYPE html>
< html xmlns="https://www.w3.org/1999/xhtml">
< head>
< meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<link href="Microsoft.WinJS.2.1/css/ui-light.css" rel="stylesheet" />>
<script src="Microsoft.WinJS.2.1/js/base.js"></script>
<script src="Microsoft.WinJS.2.1/js/ui.js"></script>
<style>
#listItem {
width:300px;
}
#productImg {
height:50px;
width:50px;
margin:5px;
display:-ms-flexbox;
display:-webkit-flex;
}
#description {
margin:5px;
display:-ms-flexbox;
display:-webkit-flex;
}
#listView {
width:1000px;
height:500px;
}
</style>
<script>
(function () {
//データバインドするデータ
var dataArray = [
{ title: "りんご", text: "リンゴ(林檎、学名:Malus pumila)", picture: "img/apple.png" },
{ title: "オレンジ", text: "甘橙(学名:Citrus sinensis)", picture: "img/orange.png" },
{ title: "マンゴー", text: "(檬果、芒果、学名:Mangifera indica)",
picture: "img/mango.png" },
{ title: "バナナ", text: "(甘蕉、実芭蕉、学名 Musa spp. )", picture: "img/banana.png" }
];
//オブジェクトの配列からバインディングリストを生成
var itemList = new WinJS.Binding.List(dataArray);
//マークアップ内からアクセス可能とするためネームスペース
var publicMembers ={
itemList: itemList
};
WinJS.Namespace.define("DataExample", publicMembers);
//WinJS コントロールを表示すめための処理
document.addEventListener("DOMContentLoaded", function () {
WinJS.UI.processAll();
});
})();
</script>
< /head>
< body>
<!-- テンプレートの定義-->
< div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template">
<div id="listItem" >
<!-- "picture" フィールドを表示 -->
< img id="productImg" data-win-bind="alt: title; src: picture" src="#" />
<div id="description">
<!-- "title" フィールドを表示 -->
<h4 data-win-bind="innerText: title"></h4>
<!-- "text" フィールドを表示 -->
< h6 data-win-bind="innerText: text"></h6>
</div>
</div>
</div>
<!--ListView の定義 -->
< div id="listView" data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource:DataExample.itemList.dataSource,
itemTemplate:select('#mediumListIconTextTemplate'),
itemsDraggable: true,
itemsReorderable: true,
layout:{type:WinJS.UI.GridLayout}}"></div>
< /body>
< /html>
ListView のプロパティを JavaScript から設定する記述方法
前述のサンプルでは、ListView を表すタグの date-win-option アトリビュートで ListView のプロパティを設定していましたが、JavaScript から ListView コントロールのインスタンスに対し設定を行うことができます。これは条件などによってバインドするデータが変化する場合に便利です。
この方法では、date-win-option アトリビュートを記述しないため ListView を表すマークアップも以下のようにシンプルにできます。
<!--ListView の定義 -->
< div id="listView" data-win-control="WinJS.UI.ListView"></div>
データのバインドと ListView コントロールへのテンプレートの設定は、WinJS.UI.processAll メソッドが返す Promise オブジェクトの then か done メソッドの引数として渡した関数内で行います。この関数内では、ListView コントロールのすべてのプロパティにアクセスできます。
具体的な記述は以下の通りです。
//WinJS コントロールを表示するための処理
document.addEventListener("DOMContentLoaded", function () {
WinJS.UI.processAll().then(initialize);
});
//ListView コントロールの初期化
function initialize() {
var itemTemplate = document.getElementById("itemTemplate");
var listView = document.getElementById("listView").winControl;
listView.itemDataSource = new WinJS.Binding.List(dataArray).dataSource;
listView.itemTemplate = itemTemplate;
}
また、マークアップから JavaScript のデータソースにアクセスさせるために行っていたネームスペースへの登録も不用になります。
HTML 全体の内容は以下のとおりです。
<!DOCTYPE html>
< html xmlns="https://www.w3.org/1999/xhtml">
< head>
< meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
< link href="Microsoft.WinJS.2.1/css/ui-light.css" rel="stylesheet" />>
<script src="Microsoft.WinJS.2.1/js/base.js"></script>
<script src="Microsoft.WinJS.2.1/js/ui.js"></script>
<style>
#listItem {
width:300px;
}
#productImg {
height:50px;
width:50px;
margin:5px;
display:-ms-flexbox;
display:-webkit-flex;
}
#description {
margin:5px;
display:-ms-flexbox;
display:-webkit-flex;
}
#listView {
width:1000px;
height:500px;
}
</style>
<script>
(function () {
//データバインドするデータ
var dataArray = [
{ title: "りんご", text: "リンゴ(林檎、学名:Malus pumila)", picture: "img/apple.png" },
{ title: "オレンジ", text: "甘橙(学名:Citrus sinensis)", picture: "img/orange.png" },
{ title: "マンゴー", text: "(檬果、芒果、学名:Mangifera indica)",
picture: "img/mango.png" },
{ title: "バナナ", text: "(甘蕉、実芭蕉、学名 Musa spp. )", picture: "img/banana.png" }
];
//WinJS コントロールを表示するための処理
document.addEventListener("DOMContentLoaded", function () {
WinJS.UI.processAll().then(initialize);
});
//ListView コントロールの初期化
function initialize() {
var itemTemplate = document.getElementById("itemTemplate");
var listView = document.getElementById("listView").winControl;
listView.itemDataSource = new WinJS.Binding.List(dataArray).dataSource;
listView.itemTemplate = itemTemplate;
}
})();
</script>
< /head>
< body>
<!-- テンプレートの定義-->
< div id="itemTemplate" data-win-control="WinJS.Binding.Template">
<div id="listItem">
<!-- "picture" フィールドを表示 -->
< img id="productImg" data-win-bind="alt: title; src: picture" src="#" />
<div id="description">
<!-- "title" フィールドを表示 -->
<h4 data-win-bind="innerText: title"></h4>
<!-- "text" フィールドを表示 -->
< h6 data-win-bind="innerText: text"></h6>
</div>
</div>
</div>
<!--ListView の定義 -->
< div id="listView" data-win-control="WinJS.UI.ListView"></div>
< /body>
< /html>
表示されるリストは同じものです。
まとめ
今回は、WinJS2.1 の提供するテンプレートとデータバインドの機能を、ListView コントロールを使用して説明しました。
ListView コントロールは単にアイテムを列挙して表示するだけでなく、プロパティの設定によって、並べ替えやドラッグドロップなどが簡単に実装できますのでぜひお試しください。
ListView で並べ替え、ドラッグ操作、ドロップ操作を有効にする方法
https://msdn.microsoft.com/ja-jp/library/windows/apps/dn423315.aspx
<参考>
クイック スタート: ListView の追加 (HTML)
https://msdn.microsoft.com/ja-jp/library/windows/apps/hh465496.aspx