Windows 8 Metro アプリケーションで入れ子になった ListView に問題があります。エラーが発生します:
Exception was thrown at line 5840, column 33 in
ms-appx://microsoft.winjs.1.0/js/base.js 0x800a138f - JavaScript runtime error:
Unable to get property 'dataSource' of undefined or null reference
コードは次のとおりです。
<div id="color" data-win-control="WinJS.Binding.Template">
<div>color</div>
</div>
<div id="row" data-win-control="WinJS.Binding.Template">
<div>
<div>row</div>
<div
data-win-control="WinJS.UI.ListView"
data-win-options="{ itemDataSource : colorsDataSource.dataSource,
itemTemplate: select('#color')}">
</div>
</div>
</div>
<div id="basicListView"
data-win-control="WinJS.UI.ListView"
data-win-options="{ itemDataSource : Data.rowsDataSource.dataSource,
itemTemplate: select('#row')}">
</div>
問題のある行は次のとおりです。
data-win-options="{ itemDataSource : colorsDataSource.dataSource,
itemTemplate: select('#color')}"
問題は、data-win-options が評価されている瞬間に、colorsDataSource に何らかの形でアクセスできないことです。なぜなら、データ構造 Data は静的であり、UI が解析される前に初期化されるためです (args.setPromise(WinJS の前) .UI.processAll());)。
たとえば、行テンプレートを次のように変更しようとすると:
<div id="row" data-win-control="WinJS.Binding.Template">
<div>
<div>row</div>
<div data-win-bind="innerText: colorsDataSource.dataSource" ></div>
</div>
</div>
正しく出力される[オブジェクトオブジェクト]...
JavaScript 構造のデータは次のようになります。
var rows = new WinJS.Binding.List([]);
model.rows.forEach(function (row) {
rows.push({
colorsDataSource : new WinJS.Binding.List(row.rowData.colors)
});
});
Data.rowsDataSource = rows;
編集: うーん、私は理由を見つけました( base.jsの属性data-win-optionsの処理):
var options;
var optionsAttribute = element.getAttribute("data-win-options");
if (optionsAttribute) {
options = WinJS.UI.optionsParser(optionsAttribute, global, {
select: createSelect(element)
});
}
オプションはグローバルコンテキストで評価されます。つまり、現在処理されているアイテム (私の場合は行アイテム)を取得する方法はありません...
回避策は、カスタム レンダラー (カスタム コントロール全体) を作成することです。ここで部分的に説明されているhttp://stephenwalther.com/archive/2012/05/23/metro-dynamically-switching-templates-with-a-winjs-listview.aspx - itemTemplateFunction を参照