问题
I have problem with nested ListViews in a Windows 8 Metro application. I get error:
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
The code is:
<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>
The problematic line is:
data-win-options="{ itemDataSource : colorsDataSource.dataSource,
itemTemplate: select('#color')}"
The problem is that at the moment when the data-win-options is being evaluated the colorsDataSource is somehow not accessible - not sure why, because the data structure Data is static and initialized before the UI is even parsed (before args.setPromise(WinJS.UI.processAll());).
For example when I try modify the row template to this:
<div id="row" data-win-control="WinJS.Binding.Template">
<div>
<div>row</div>
<div data-win-bind="innerText: colorsDataSource.dataSource" ></div>
</div>
</div>
It outputs correctly [object Object]...
The javascript structure Data looks like this:
var rows = new WinJS.Binding.List([]);
model.rows.forEach(function (row) {
rows.push({
colorsDataSource : new WinJS.Binding.List(row.rowData.colors)
});
});
Data.rowsDataSource = rows;
EDIT: Hm, I found the reason (processing of the attribute data-win-options in base.js):
var options;
var optionsAttribute = element.getAttribute("data-win-options");
if (optionsAttribute) {
options = WinJS.UI.optionsParser(optionsAttribute, global, {
select: createSelect(element)
});
}
The options are evaluated in global context, that means there is no way how to get currently processed item (in my case the row item)...
Workaround is to create custom renderer (whole custom control). Which is partly described here http://stephenwalther.com/archive/2012/05/23/metro-dynamically-switching-templates-with-a-winjs-listview.aspx - see itemTemplateFunction
回答1:
Nested listviews basically don't work and aren't supported. You won't find an easy answer, unfortunately.
回答2:
As Chris Tavares states, nested ListViews are not supported.
However, the bigger reason this doesn't work, is that you need to some how obtain the data itself on the next control (lets ignore that it's a list view for now).
You've tried to resolve this using the data-win-options
attribute, which as you correctly pointed out only resolves to the global namespace.
There is a work around to this -- use a data binding.
Where you have:
<div data-win-control="WinJS.UI.ListView"
data-win-options="{ itemDataSource : colorsDataSource.dataSource,
itemTemplate: select('#color')}">
</div>
Remove the itemsDataSource
from data-win-options
, and move it to a data-win-bind:
<div data-win-control="WinJS.UI.ListView"
data-win-options="{ itemTemplate: select('#color')}"
data-win-bind="winControl.itemDataSource: colorsDataSource.dataSource">
</div>
This assumes that colorsDataSource is a property off the item that is being rendered. e.g. your row object.
To solve your nested problem, it looks like your "parent" listview could go away -- just create the elements dynamically based on your datasource.
来源:https://stackoverflow.com/questions/13218412/winjs-nested-listviews