Windows 8 CP and VS11 are around. Recently I wrote Setting up Visual Studio11 Beta for Metro Application Creation . In this post let us get into some development.
In this post we will see
- Creating DataSource
- ListView Binding to DataSource
- Creating ItemTemplate
- Grouping Data Source
- Using SemanticZoomView over ListView
At the end of the post we will have output like below,
We are going to display list of movies in a ListView. Movies will be grouped with the first letter of their title. Later in the post we will apply SemanticZoomView on the ListView . In above image you can see Semantic Zoom View. To switch between SemanticZoomView and detail view either you can tap on the screen or press CTRL + Arrow key on the keyboard.
Create DataSource
Very first we need to create a DataSource. To create DataSource right click on JS folder and add a new JavaScript file. Let us call this newly added JavaScript file as moviedata.js
Inside newly created file, we need to create an anonymous JavaScript function and define a JavaScript array. This array contains locally data to be bind to the ListView.
MovieArray contains two properties,
- Title to display name of the movie
- Picture to display thumbnail of the movie.
All the movie images are inside images folder in the project. Let us create array with sample data. Array is given below.
var movieArray = [ { title: "The Artist", picture: "images/TheArtist.jpg" }, { title: "A Better Life", picture: "images/abetterlife.jpg" }, { title: "Abduction", picture: "images/abduction.jpg" }, { title: "African Cats", picture: "images/africancats.jpg" }, { title: "Angel Crest", picture: "images/angelscrest.jpg" }, { title: "Arthur", picture: "images/arthur.jpg" }, { title: "Anonymous", picture: "images/anonymous.jpg" }, { title: "A Dangerous Method", picture: "images/adangerousmethod.jpg" }, { title: "A Good Old Fashioned Orgy ", picture: "images/agoodoldfashionedorgy.jpg" }, { title: "A Seperation ", picture: "images/aseparation.jpg" }, { title: "Another Earth ", picture: "images/anotherearth.jpg" }, { title: "A Heartbeat Away ", picture: "images/aheartbeataway.jpg" }, { title: "Bad Teacher ", picture: "images/badteacher.jpg" }, { title: "Begineers ", picture: "images/beginners.jpg" }, { title: "Brotherhood ", picture: "images/brotherhood.jpg" }, { title: "Bridesmaids ", picture: "images/bridesmaids.jpg" }, { title: "Born To Be Wild ", picture: "images/borntobewild.jpg" }, { title: "Blackthorn ", picture: "images/blackthorn.jpg" }, { title: "Bellflower ", picture: "images/bellflower.jpg" }, { title: "Butter ", picture: "images/butter.jpg" }, { title: "Bunraku ", picture: "images/bunraku.jpg" }, { title: "Cars 2 ", picture: "images/cars2.jpg" }, { title: "Cost Of A Soul", picture: "images/costofasoul.jpg" }, { title: "Carnage ", picture: "images/carnage.jpg" }, { title: "Crazy Stupid Love ", picture: "images/crazystupidlove.jpg" }, { title: "Cracks ", picture: "images/cracks.jpg" }, { title: "Colombiana ", picture: "images/colombiana.jpg" }, { title: "Cedar Rapids ", picture: "images/cedarrapids.jpg" }, { title: "Captain America ", picture: "images/captainamerica.jpg" }, ];
Next we need to convert JavaScript array into list to be bind to ListView.
Now to make this data publicly available we need to make a namespace and on the HTML page need to add reference of this namespace to use data from this file. Namespace can be created as below,
There are few points worth discussing about creating namespace
- MovieData.itemList is the public member.
- MovieData.itemList.datasource will be the datasource.
By this step we have created DataSource. And putting all piece of code together moviedata.js file will be as below,
Moviedata.js
(function () { "use strict"; // http://www.allmoviephoto.com/photo/index_2011.html var movieArray = [ { title: "The Artist", picture: "images/TheArtist.jpg" }, { title: "A Better Life", picture: "images/abetterlife.jpg" }, { title: "Abduction", picture: "images/abduction.jpg" }, { title: "African Cats", picture: "images/africancats.jpg" }, { title: "Angel Crest", picture: "images/angelscrest.jpg" }, { title: "Arthur", picture: "images/arthur.jpg" }, { title: "Anonymous", picture: "images/anonymous.jpg" }, { title: "A Dangerous Method", picture: "images/adangerousmethod.jpg" }, { title: "A Good Old Fashioned Orgy ", picture: "images/agoodoldfashionedorgy.jpg" }, { title: "A Seperation ", picture: "images/aseparation.jpg" }, { title: "Another Earth ", picture: "images/anotherearth.jpg" }, { title: "A Heartbeat Away ", picture: "images/aheartbeataway.jpg" }, { title: "Bad Teacher ", picture: "images/badteacher.jpg" }, { title: "Begineers ", picture: "images/beginners.jpg" }, { title: "Brotherhood ", picture: "images/brotherhood.jpg" }, { title: "Bridesmaids ", picture: "images/bridesmaids.jpg" }, { title: "Born To Be Wild ", picture: "images/borntobewild.jpg" }, { title: "Blackthorn ", picture: "images/blackthorn.jpg" }, { title: "Bellflower ", picture: "images/bellflower.jpg" }, { title: "Butter ", picture: "images/butter.jpg" }, { title: "Bunraku ", picture: "images/bunraku.jpg" }, { title: "Cars 2 ", picture: "images/cars2.jpg" }, { title: "Cost Of A Soul", picture: "images/costofasoul.jpg" }, { title: "Carnage ", picture: "images/carnage.jpg" }, { title: "Crazy Stupid Love ", picture: "images/crazystupidlove.jpg" }, { title: "Cracks ", picture: "images/cracks.jpg" }, { title: "Colombiana ", picture: "images/colombiana.jpg" }, { title: "Cedar Rapids ", picture: "images/cedarrapids.jpg" }, { title: "Captain America ", picture: "images/captainamerica.jpg" }, ]; var dataList = new WinJS.Binding.List(movieArray);
Creating ListView
We have created data source and ahead and create a ListView. In ListView we need to set itemDataSource to MovieData.itemList.dataSource.
If you remember while creating data source we have created public namespace with name MovieData . in MovieData.js file so we need to add reference as below.
At this point if we run the application we will get output as below. Essentially below is the same array we get as output we created as data source
Now we need to create a template to render movie image and name of the movie. An ItemTemplate for ListView can be created as below.
Inside ItemTemplate there are two controls
- Image control to render thumbnail of the movie
- Inside div rendering title of movie.
Now go ahead and set the itemTemplate of ListView as below
At this point if we run application we should get ListView as below,
You can notice automatically WinJS has added scrollbar. By this point we should have HTML file as below,
Default.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ListViewBinding</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> <!-- ListViewBinding references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> <script src="/js/moviedata.js"></script> </head> <body> <div id="headerTemplate" data-win-control="WinJS.Binding.Template" style="display: none"> <div> <h1 data-win-bind="innerText: title"></h1> </div> </div> <div id="moviesTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 130px;"> <img src="#" style="width: 100px; height: 100px;" data-win-bind="alt: title; src: picture" /> <div> <h4 data-win-bind="innerText:title"></h4> </div> </div> </div> <div id="movieListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource :MovieData.itemList.dataSource, itemTemplate:moviesTemplate, layout: {type: WinJS.UI.GridLayout} }"> </div> </body> </html>
Customizing ListView
If we see the ListView, it is not that immersive. we can customize a ListView by overriding the CSS. Each HTML file got a corresponding CSS file associated. For example for default.html there is a css file default.css.Now let us go ahead and override ListView properties. In below CSS
- ListView height and width is set to 600 pixels and 800 pixels respectively
- ListView border is set to 2 Pixel
- Margin of each item in ListView is set to 10 Pixel
- On hover on each item color would get changed to Red.
We need to put above CSS in default.css . After that when we run the application, we will get ListView as below. You can notice that on mouse hover color is changing to Red.
Grouping of ListView Items
To group the items in ListView, we need to call CreateGrouped JavaScript function from base.js. This function is defined as below
we can see that it takes three parameters. Explanation of parameters are given below
As you see createGrouped function takes three functions as input parameter. So let us create these functions one by one.
Below function will compare the groups. This function will be groupSorter
This function will return group of the item.
Below function will return Title of the group. In this case items would be grouped with first letter.
In last step we need to call above three functions to create group and make a public namespace for this that is it accessible from other files.
By putting all codes together in mymoviedata.js file you will have two public namespaces. You need to set MovieGroupedData as datasource of ListView to create grouped data.
MovieGroupedData.js
(function () { "use strict"; // http://www.allmoviephoto.com/photo/index_2011.html var movieArray = [ { title: "The Artist", picture: "images/TheArtist.jpg" }, { title: "A Better Life", picture: "images/abetterlife.jpg" }, { title: "Abduction", picture: "images/abduction.jpg" }, { title: "African Cats", picture: "images/africancats.jpg" }, { title: "Angel Crest", picture: "images/angelscrest.jpg" }, { title: "Arthur", picture: "images/arthur.jpg" }, { title: "Anonymous", picture: "images/anonymous.jpg" }, { title: "A Dangerous Method", picture: "images/adangerousmethod.jpg" }, { title: "A Good Old Fashioned Orgy ", picture: "images/agoodoldfashionedorgy.jpg" }, { title: "A Seperation ", picture: "images/aseparation.jpg" }, { title: "Another Earth ", picture: "images/anotherearth.jpg" }, { title: "A Heartbeat Away ", picture: "images/aheartbeataway.jpg" }, { title: "Bad Teacher ", picture: "images/badteacher.jpg" }, { title: "Begineers ", picture: "images/beginners.jpg" }, { title: "Brotherhood ", picture: "images/brotherhood.jpg" }, { title: "Bridesmaids ", picture: "images/bridesmaids.jpg" }, { title: "Born To Be Wild ", picture: "images/borntobewild.jpg" }, { title: "Blackthorn ", picture: "images/blackthorn.jpg" }, { title: "Bellflower ", picture: "images/bellflower.jpg" }, { title: "Butter ", picture: "images/butter.jpg" }, { title: "Bunraku ", picture: "images/bunraku.jpg" }, { title: "Cars 2 ", picture: "images/cars2.jpg" }, { title: "Cost Of A Soul", picture: "images/costofasoul.jpg" }, { title: "Carnage ", picture: "images/carnage.jpg" }, { title: "Crazy Stupid Love ", picture: "images/crazystupidlove.jpg" }, { title: "Cracks ", picture: "images/cracks.jpg" }, { title: "Colombiana ", picture: "images/colombiana.jpg" }, { title: "Cedar Rapids ", picture: "images/cedarrapids.jpg" }, { title: "Captain America ", picture: "images/captainamerica.jpg" }, ]; var dataList = new WinJS.Binding.List(movieArray); function compareGroups(left, right) { return left.charCodeAt(0) - right.charCodeAt(0); } function getGroupKey(dataItem) { return dataItem.title.toUpperCase().charAt(0); } function getGroupData(dataItem) { return { title: dataItem.title.toUpperCase().charAt(0) }; } var publicMembers = { itemList: dataList }; WinJS.Namespace.define("MovieData", publicMembers); var groupedItemsList = dataList.createGrouped(getGroupKey, getGroupData, compareGroups); WinJS.Namespace.define("MovieGroupedData", { groupedItemsList: groupedItemsList }); })();
By this point we have created functions to group data .Next we need to modify ListView datasource to group ListView items. For that let us created a header template. Header template will display Title of the group. Header Template can be created in the same way of Item Template. Header template is given below
And we have already created Item Template as following.
To group items in ListView we need to create Header Template and Item Template. We have created this in previous step. Next we need to set datasource of the ListView to bind grouped items. ListView can be created as below for the grouped items
If we put all codes together then default.html will have following codes.
Default.html
Let us go ahead and run the application. We should be getting output as following.
We have grouped items in ListView. Next let us add Semantic View. To add Semantic View you need to put ListView in side Semantic View control. In Semantic Zoom we will have two views of same ListView. We need to create a view for the zoom out . For zoom out Template can be created as given below.
After creation of Template let us go ahead and create a ListView for Zoom Out view.
ItemDataSource of zoomed ListView is same as of the zoomed in ListView. Now we need to put both ListView , Zoomed In and Zoomed out in the Semantic Zoom control. We can put ListView controls in Semantic Zoom control as below
Now we should have default.html as following
Default.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ListViewBinding</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> <!-- ListViewBinding references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> <script src="/js/moviedata.js"></script> </head> <body> <div id="headerTemplate" data-win-control="WinJS.Binding.Template" style="display: none"> <div> <h1 data-win-bind="innerText: title"></h1> </div> </div> <div id="moviesTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 130px;"> <img src="#" style="width: 100px; height: 100px;" data-win-bind="alt: title; src: picture" /> <div> <h4 data-win-bind="innerText:title"></h4> </div> </div> </div> <!--<div id="movieListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource :MovieData.itemList.dataSource, itemTemplate:moviesTemplate, layout: {type: WinJS.UI.GridLayout} }"> </div> --> <h1>Rate Movies Application</h1> <div id="movieListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : MovieGroupedData.groupedItemsList.dataSource, groupDataSource: MovieGroupedData.groupedItemsList.groups.dataSource, itemTemplate: moviesTemplate, groupHeaderTemplate: headerTemplate, layout: {type: WinJS.UI.GridLayout} }"> </div> </body> </html>
Next we need to add some CSS to make it more immersive. In default.css , we need to add below css
.win-listview { height: 600px; width: 800px; border: 2px solid gray; } .win-listview .win-container { margin: 10px; } .win-listview .win-container:hover { background-color: red; border-color: red; } .semanticZoomItem { width: 130px; height: 130px; background-color: rgba(38, 160, 218, 1.0); } .semanticZoomItem .semanticZoomItem-Text { padding: 10px; line-height: 150px; white-space: nowrap; color: white; }
On running we should be getting the below output
On tapping or pressing of crtl and arrow key you should be getting the semantic zoom view. Semantic Zoom View of ListView is as following image.
In this way we can work ListView and SemanticZoom WinJS controls. In further post we will try to pull data from service. I hope this post is useful. Thanks for reading.
Follow @debug_modeFiled under: Windows Store Apps
