Binding WinJS.UI.ListView to data source
-
23 апреля 2012 г. 10:36
Hi,
I've been trying to get a WinJS.UI.ListView to work with a data source and I have followed the instructions here about how to do it. What I don't get is how it populates the items on load as it isn't calling the itemsFromIndex method when it's bound.
I have looked at this article too.
Here is my data.js file:
(function () { "use strict"; //http://64.4.30.156/en-us/library/windows/apps/hh770849.aspx var dataAdapter = WinJS.Class.define(function () { }, { itemsFromIndex: function (requestIndex, countBefore, countAfter) { var requestStr = "http://localhost:47317/api/values", that = this; return WinJS.xhr({ url: requestStr }).then(function (request) { var items = JSON.parse(request.responseText), results = []; for (var i = 0, itemsLength = items.length; i < itemsLength; i++) { /* IItem: http://64.4.30.156/en-us/library/windows/apps/br212592.aspx data: Gets or sets the item's data. handle: Gets the temporary ID of the item. index: Gets the item's index in the IListDataSource. key: Gets or sets the key the identifies the item. */ var Item = { key: i.toString(), data: { TopLine: items[i].TopLine } } results.push(Item); } /* IFetchResult: http://64.4.30.156/en-us/library/windows/apps/br212548.aspx absoluteIndex: Gets or sets the index of the requested item in the IListDataAdapter object's data source. atEnd: Gets or sets a value that indicates whether this IFetchResult contains the last items at the end of the IListDataAdapter object's data source. atStart: Gets or sets a value that indicates whether this IFetchResult contains the first items at the beginning of the IListDataAdapter object's data source. items: Gets or sets the items returned by the fetch operation. offset: Gets or sets the location of the requested item within the items array. totalCount: Gets or sets the number of items in the IListDataAdapter object's underlying data source. */ var FetchResult = { items: results, offset: 0, totalCount: results.length } return FetchResult; }, function (request) { return WinJS.UI.FetchError.noResponse; }); }, getCount: function () { var requestStr = "http://localhost:47317/api/values", that = this; return WinJS.xhr({ url: requestStr }).then(function (request) { var obj = JSON.parse(request.responseText); try { return obj.length; } catch (err) { return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.noResponse)); } }) } }); var dataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function () { this._baseDataSourceConstructor(new dataAdapter()); }); WinJS.Namespace.define("appData", { dataSource: dataSource }); })();
Все ответы
-
24 апреля 2012 г. 9:39
How do you define your ListView in html?
I think you should create an instance of dataSource like: new appData.dataSource() -
1 мая 2012 г. 7:00
Hi,
I define it like this:
<div data-win-control="WinJS.UI.ListView" data-win-options="{itemDataSource : appData.dataSource, itemTemplate: select('#template'), selectionMode: 'single'}}"> </div>Even if I define it in the code it doesn't run an initialization to get the items.@williamparry
-
1 мая 2012 г. 18:34Модератор
Hi William,
Just to make sure I completely understand, your data is not populating correct?
After you populate the data source you should assign that datasource and the template to the list view. This should trigger your code.
This sample is the implementation of that walktrough code and it would be helpful if you inspected this and compared it to your code:
http://code.msdn.microsoft.com/windowsapps/ListView-custom-data-4dcfb128\
You can trace through this working sample and perhaps discover what you are doing differently.
-Jeff
Jeff Sanders (MSFT)
- Предложено в качестве ответа Jeff SandersMicrosoft Employee, Moderator 1 мая 2012 г. 18:34
-
2 мая 2012 г. 17:10
This sample is the implementation of that walktrough code and it would be helpful if you inspected this and compared it to your code:
http://code.msdn.microsoft.com/windowsapps/ListView-custom-data-4dcfb128\
This is a very useful sample. However, getCount() on the datasource is implemented as an additional API call to the service. Is that the best we can do? Many search APIs provide the total count alongside the results - so implementing things this way would mean making the same call twice.
-
2 мая 2012 г. 21:19
This sample is the implementation of that walktrough code and it would be helpful if you inspected this and compared it to your code:
http://code.msdn.microsoft.com/windowsapps/ListView-custom-data-4dcfb128\
This sample doesn't implement oniteminvoked for the photos coming back from the api. In the boilerplate code, this method uses the index that was clicked against a static datasource to find which item was invoked. In the case of a list bound to an api, how should you do it? I assume we don't need to go back to the api, right?
-
6 мая 2012 г. 3:51
I've matched it up with the Bing example and gone through the tutorial on how to use a custom data source.
I've stepped through the Bing example and my own code. Both process getCount() and then return the results from the service call, but mine doesn't get to:
function postFetch() { if (!fetchesPosted) { fetchesPosted = true; msSetImmediate(function () { fetchesPosted = false; fetchItemsForAllSlots(); }); } }(line 3802 in ui.js)
@williamparry
-
7 мая 2012 г. 18:06Модератор
Hi William,
Just to make sure I completely understand, your data is not populating correct?
-Jeff
Jeff Sanders (MSFT)
-
7 мая 2012 г. 22:27
Hi Jeff,
It's not populating and I'm not sure why it's not reaching the postFetch() method like the Bing example does.
@williamparry
-
8 мая 2012 г. 18:55
This sample is the implementation of that walktrough code and it would be helpful if you inspected this and compared it to your code:
http://code.msdn.microsoft.com/windowsapps/ListView-custom-data-4dcfb128\
This sample doesn't implement oniteminvoked for the photos coming back from the api. In the boilerplate code, this method uses the index that was clicked against a static datasource to find which item was invoked. In the case of a list bound to an api, how should you do it? I assume we don't need to go back to the api, right?
FWIW, Someone pointed me at an example which shows how to handle iteminvoked correctly: http://code.msdn.microsoft.com/windowsapps/ListView-basic-usage-sample-fcc451db
Basically, in the event object, there is a details object, with an itemPromise object, which will in turn return the invoked item:
eventObject.detail.itemPromise.then(function (invokedItem) { // Access item data from the itemPromise nav.navigate("/html/groupDetailPage.html", { group: invokedItem.data }); });
-
10 мая 2012 г. 15:23Модератор
William,
Can you send me a simplified sample with the problem? http://blogs.msdn.com/jpsanders/contact.aspx
-Jeff
Jeff Sanders (MSFT)
-
23 мая 2012 г. 13:06
Hi MSAD(metro style app dev),
I'm using the same approach(VirtualizedDataSource and dataAdapter for listview as mentioned in sample app titled "working with data source" which fetches data from Bing). I'm getting data from remote data source . But only if i "Continue" the execution of program.
The error is " JavaScript runtime error: Unable to get value of the property 'uniqueID': object is null or undefined ".
I dont understand what exactly is this ?
It is at > _recordFromElement [ui.js] Line 9720
Can anybody please tell me how to get rid of this weird bug ? Maybe, I'm doing something wrong..
Thanks,
{Web-Farmer}
-
23 мая 2012 г. 13:11Модератор
I don't know what you mean by "I'm getting data from remote data source . But only if i "Continue" the execution of program.".
Can you give us more details? Does the sample work OK for you unmodified? If so, what exactly are you doing differently in your code? That may give you a clue as to what is failing.
-Jeff
Jeff Sanders (MSFT)
-
23 мая 2012 г. 14:12
hi Jeff,
thanks for your prompt reply..
Well, yes i have modified that sample to use our set of api instead of calling bing image services.
What i'm doing is same as William as mentioned in first post in this ongoing thread.
When i run this app, its throws an exception and shows me an error " JavaScript runtime error: Unable to get value of the property 'uniqueID': object is null or undefined ". If there is a handler for this exception, the program may be safely continued."
So i clicked "Continue" and i get the result data from API that i'm calling using VirtualizedDataSource and iDataAdapter.
The problem is that error i'm not able to figuring out what causes that error..
THanks,
-
23 мая 2012 г. 14:15Модератор
If you can give me a simple repro I can look into this further.
http://blogs.msdn.com/jpsanders/contact.aspx
-Jeff
Jeff Sanders (MSFT)
-
23 мая 2012 г. 14:31
I have created default metro style app for javascript with blank template..
1) this is in gridData.js
// global for the datasource definition var iMatchDataSource = iMatchDataSource || {}; (function () { // Definition of the data adapter var iMatchDataAdapter = WinJS.Class.define( function (devkey, query) { // Constructor this._minPageSize = 10; // based on the default of 10 this._maxPageSize = 50; // max request size for bing images this._maxCount = 1000; // limit on the bing API this._devkey = devkey; this._query = query; this._SUCCESS_ = 1; this._ERROR_ = 2; }, // Data Adapter interface methods // These define the contract between the virtualized datasource and the data adapter. // These methods will be called by virtualized datasource to fetch items, count etc. { // This example only implements the itemsFromIndex and count methods // Called to get a count of the items // The value of the count can be updated later in the response to itemsFromIndex getCount: function () { var that = this; return that._maxCount; }, // Called by the virtualized datasource to fetch items // It will request a specific item and hints for a number of items either side of it // The implementation should return the specific item, and can choose how many either side // to also send back. It can be more or less than those requested. // // Must return back an object containing fields: // items: The array of items of the form items=[{ key: key1, data : { field1: value, field2: value, ... }}, { key: key2, data : {...}}, ...]; // offset: The offset into the array for the requested item // totalCount: (optional) update the value of the count itemsFromIndex: function (requestIndex, countBefore, countAfter) { var that = this; //Build up the URL for the request var requestStr = "my url is here"; //Return the promise from making an XMLHttpRequest to the server return WinJS.xhr({ url: requestStr }).then( //Callback for success function (request) { var results = [], count; console.log("resp"); // Use the JSON parser on the results, safer than eval var obj = JSON.parse(request.responseText); console.log(obj.DATA.resData); // Verify if the service has returned images if (true) { var items = [], itemsLength; items = obj.DATA.resData; // Data adapter results needs an array of items of the shape: // items =[{ key: key1, data : { field1: value, field2: value, ... }}, { key: key2, data : {...}}, ...]; // Form the array of results objects for (var i = 0, itemsLength = items.length; i < itemsLength; i++) { var dataItem = items[i]; results.push({ key: i.toString(), data: { title: dataItem.user_company_name, thumbnail: dataItem.advertiser_company_logo_path, linkurl: dataItem.noofcoupons } }); } // Get the count from the json count = obj.DATA.total; return { items: results, // The array of items offset: 0, // The offset into the array for the requested item totalCount: 10 // Total count of records, bing will only return 1000 so we cap the value }; } else { return WinJS.UI.FetchError.doesNotExist; } }, //Called on an error from the XHR Object function (request) { return WinJS.UI.FetchError.noResponse; }); } // setNotificationHandler: not implemented // itemsFromStart: not implemented // itemsFromEnd: not implemented // itemsFromKey: not implemented // itemsFromDescription: not implemented }); iMatchDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function (devkey, query) { this._baseDataSourceConstructor(new iMatchDataAdapter(devkey, query)); }); })();2) this is in default.js
WinJS.UI.processAll().done(function () { var listview = id("listview1").winControl; var myTemplate = id("itemTemplate"); //Create the bing itemDataSource var myDataSrc = new iMatchDataSource("1", "2"); // Set the properties on the list view to use the itemDataSource listview.itemDataSource = myDataSrc; listview.itemTemplate = myTemplate; });3) and here goes default.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Application1</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.0.6/js/base.js"></script> <script src="//Microsoft.WinJS.0.6/js/ui.js"></script> <!-- Application1 references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/gridData.js"></script> <script src="/js/default.js"></script> </head> <body> <p>Content goes here</p> <div class="item" id="scenarioOutput"> <div id="itemTemplate" data-win-control="WinJS.Binding.Template"> <div class="itemTempl"> <img data-win-bind="src: thumbnail" alt="Databound image" /> <span class="content" data-win-bind="innerText: title"></span> </div> </div> <div id="listview1" class="box" data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'none', tapBehavior: 'none', swipeBehavior: 'none', layout: { type: WinJS.UI.GridLayout, maxRows: 10 } }" ></div> </div> </body> </html>
-
23 мая 2012 г. 14:34МодераторI am sorry I was not clear. I want to run your repro here and debug it.
Jeff Sanders (MSFT)
-
23 мая 2012 г. 14:36
I want to make a data grid control which fetch data from remote data services and it would load the data as user scroll the view(list view).. a kinda of lazy loading of data or infinite scroll...
So i'm experimenting above code.
-
24 мая 2012 г. 5:53
Jeff, can you please look this issue when you view this thread again ?
Or is there any other way without using datasource and data adapter along with listView.
I'm thinking just to use XHR only and when it returns promises then i will populate the listview with WinJS.Binding.List(arg); where arg is the result from remote web services..normally an array or json.
So every time when user scroll the listview, i will call the XHR and push the data into my "xyz" list.
This is what i'm planning to do now..
If you get anything that help me to achieve this scenario then please share it..
Thanks
-
24 мая 2012 г. 12:31МодераторAgain, I need a physical repro of this.
Jeff Sanders (MSFT)

