the next door (so called) geek @rakkimk | your next door geek | friend | blogs mostly on technology, and gadgets.

WinJS – Creating a ListView, and Binding it to a List populated from an RSS feed

In this post, I would like to talk about how easy it is to reading an RSS feed, create a List, and bind it to a ListView. For this, I’m going to take an idea of mine which I already turned into an app, and it is available in the Windows Store. This, ‘NASA Image of the Day IOTD’ app of mine pulls the RSS feed from NASA site, and displays it in the app. This also stores the last 6 images you viewed using this in the application’s roamingStorage. I fetch the image, and add it to a WinJS.Binding.List, and bind the same to WinJS.UI.ListView control in the page. Before going into fetching the RSS feed, and creating the List, let’s spend sometime in understanding the ListView control better.

Here is a simple ListView control markup:

<div id="imagesListView" data-win-control="WinJS.UI.ListView"
                data-win-options="{
                    itemTemplate: imagesListTemplate,
                    selectionMode: 'none'
                    }">
</div>

This can’t get any simpler than this, right? data-win-control defines what type of control this simple <div> needs to be turned as, “WinJS.UI.ListView”. You could pass in various options for the ListView via data-win-options. Of course, you can set these properties via javascript code as well. For a ListView, you need to associate an itemTemplate, this is nothing but defines how each individual items need to be displayed. Each item would have different properties, in our example, we might want to fetch the image’s title, source url, date as different properties of an item. So, our template is the definition of how the item is displayed in the app. Here is a simple definition of my itemTemplate:

<div id="imagesListTemplate" data-win-control="WinJS.Binding.Template">
    <div data-win-bind="innerHTML: title"></div>
    <img data-win-bind="src: source" />
    <div data-win-bind="innerHTML: date" ></div>
</div>

Perfect! Now, we have defined how individual items needs to be displayed. Note the data-win-control there “WinJS.Binding.Template”. It’s up to your CSS designing skills that you can make these items shine. Now, we have created a bare minimum ListView, and a item template for the same, now let’s try to bind some items to the List from javascript code.

When you create a simple app using Visual Studio, you would find the bare minimum code already available for your to start with. Take a moment to read the portion of the code inside app.onactivated() method, and the last line where you see WinJS.UI.processAll(), is the one which turns the normal <div> into the control that you have defined. This processes all the data-win attributes, and make your controls ready for further processing. Let’s create an init() function, and call it once the WinJS.UI.processAll() finishes. WinJS has this nice little wonder called, Promises. You could check this link to read more about them. Here is the little code that would call our init function right after finishing the processing of the all UI elements in the page.

args.setPromise(WinJS.UI.processAll().then(init));

Before reading an external RSS feed, let’s try to create a simple List, and bind it with the ListView. Here is how my simple init() function looks like:

function init() {
    var imagesList = new WinJS.Binding.List([
            { title: "Preparing NASA's Next Solar Satellite for Launch", date: "Sun May 25 2013", source: "
http://www.nasa.gov/images/content/754945main_2013-2624-full_full.jpg"},
            { title: "The Engine Burns Blue", date: "Fri May 24 2013", source: "
http://www.nasa.gov/images/content/751202main_ionengine_full.jpeg"},
            { title: "Pavlof Volcano From Station", date: "Thu May 23 2013", source: "
http://www.nasa.gov/images/content/751060main_alaskan_volcano_full_full.jpg"}
    ]);
}

We have now created a simple List, and need to bind this to the ListView. Again, it is very simple. Another 1 line code:

imagesListView.winControl.itemDataSource = imagesList.dataSource;

Now when you execute your app, you would see the ListView populated, and items been shown. Now, you can use your existing CSS skills to make the items look better. There are a few CSS classes you can override for the ListView, such as win-item, classifying each image. It would be better if you use Expression Blend to open your app, and play with these classes.

You have seen how to create a simple List, and bind it to the ListView control in a HTML/WinJS Windows Store app. Let’s now use WinJS.xhr() function to fetch an RSS feed, and read the list of items to populate our list.

WinJS.xhr({ url: "http://www.nasa.gov/rss/image_of_the_day.rss" }).then(function (rss) {

    // query the list of items in the feed
    var items = rss.responseXML.querySelectorAll("item");
    for (var n = 0; n < items.length; n++) {
        var item = {};
        item.date = new Date(items[n].querySelector("pubDate").textContent).toDateString();
        item.description = items[n].querySelector("description").textContent;
        item.source = items[n].querySelector("enclosure").attributes["url"].value;
        item.title = items[n].querySelector("title").textContent;
        item.link = items[n].querySelector("link").textContent;

        imagesList.push(item);
    }
}, function (err) {
    // handle your error here
});

Now, I can successfully display the image that I fetched from the RSS feed. Again, if you notice this particular feed, it just gives only one image always. It doesn’t give the old entries, and I didn’t see any easy way to read the old images. Instead of worrying too much, I thought, I’ll perhaps store this imagesList List to my roamingStorage, and will read from it when the app starts again. Here is a snippet that allows you to store into the roamingStorage, and retrieving the same. I convert the List into a JSON string, and convert it back to an object later.

// Storing to the roamingSettings:

var roamingSettings = applicationData.roamingSettings;
roamingSettings ["myImagesList "] = JSON.stringify(imagesList.slice(0);


// Reading it from roamingSettings:

if (roamingSettings .values["myImagesList"] != null) {
    var json = JSON.parse(roamingSettings .values["myImagesList"]);
    imagesList = new WinJS.Binding.List(json);
}

Hope someone find this useful!