A blog by Chris Sells, VP of Tools & Frameworks at Telerik. (Original post here)
The Consumer Preview of Windows 8 (aka the Win8 beta) is now
available for download, along with the matching Visual Studio 11 beta.
You can download them both from the Developer Center for Metro style Apps
and at least when I did the downloading this morning, it was smooth and
worked well. In case you’re interested, I downloaded the ISO, not the
setup, and I am currently writing this blog entry in Windows Live Writer
running inside a WMWare Workstation 8.0 virtual machine running on the
Windows 7 host OS running inside Boot Camp on my MacBook Pro. As someone
said to me this morning: “That’s a lot of VMs!” Maybe so, but the Win8
and VS11 betas are running surprisingly well inside of my Inception-box.
Metro/JS Templates for VS11 in BUILD
If
you played around with the Metro/JS templates in VS11 from the BUILD
conference in September, you’ll have noticed that the generated apps
were compliant with the Windows 8 UX style guidelines, but that two of
the templates – Grip and Split – generated large amounts of code. That’s
because these are pretty much the biggest apps that Microsoft has ever
shipped as templates. They each have multiples pages and they work hard
at being simple but feature complete Metro style apps.
However, as well as the BUILD templates implemented the Win8 UX, they code wasn’t the greatest, for the following reasons:
- The templates were attempting to codify best practices for a brand-new app model. That’s always going to take time to get right.
- There
was only so much time to get it right before BUILD – it was either have
great code or implement a great UX, so the template team chose the
latter.
- The bonehead PM in charge at the time (me) decided
it was a better choice to push the data model into each page instead of
centralizing it. That was a bad idea.
- The data model, spread
as it was across nearly every JS file in the templates, was assumed to
be static. However, the vast majority of apps get their data dynamically
from some external source and the template-generated code made that
very hard to implement.
- There were a number of features that
the templates needed that didn’t exist directly in the platform, either
in WinJS, the IE DOM or in the WinRT libraries, so the templates needed
to provide those features.
All of these reasons meant
that the functionality of the generate Grid and Split apps made for an
instructional start to building your own Metro style apps, assuming you
were willing to wade through a great deal of code. The new templates in
the Win8 beta solve nearly all of these problems.
Metro/JS Templates for VS11 Beta
Out
of the box, the Metro/JS templates in the VS11 beta (made available
today, Feb 29, 2012), get more betterer as they get more complex.Let’s
start simple and work our way up.

Blank Application
The
Blank Application template is almost the smallest Metro/JS app you can
build, except that it includes a reference to the Microsoft Windows
Library for JavaScript (aka WinJS):

And
to be clear, this is a brand new feature. Including WinJS as a
reference instead of dropping the code into each project means that MS
can shipped a single shared implementation instead of every app in the
store duplicating the code. If you want to duplicate the code into your
project, you can do so, but you’ll also have to update the URL
references to the JS and CSS files from your HTML files, like this
snippet from the generated default.html:
default.html
- <!-- 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>
In
addition to the new syntax with the leading double-slashes, that the
number of WinJS files to include is a far smaller number in the Beta.
Now it’s just base.js and ui.js, which makes it easy to decide which
one(s) you want and in what order to include them, fixing a common
problem in the BUILD bits.
One other thing that’s new in the
Blank Application template is that there are stubs for implementing
tomb-stoning to easily save and restore your app’s session state in the
default.js:
default.js
- var app = WinJS.Application;
-
- app.onactivated = function (eventObject) {
- if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
- if (eventObject.detail.previousExecutionState !== Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
- // TODO: This application has been newly launched. Initialize
- // your application here.
- } else {
- // TODO: This application has been reactivated from suspension.
- // Restore application state here.
- }
- WinJS.UI.processAll();
- }
- };
-
- app.oncheckpoint = function (eventObject) {
- // TODO: This application is about to be suspended. Save any state
- // that needs to persist across suspensions here. You might use the
- // WinJS.Application.sessionState object, which is automatically
- // saved and restored across suspension. If you need to complete an
- // asynchronous operation before your application is suspended, call
- // eventObject.setPromise().
- };
The
handling of the terminated state in the onactivated event on line 3 and
the checkpoint event handler on like 16 are for reactivating and saving
your app state respectively.
And finally, the handy TODO
comments are something you’ll find sprinkled throughout the templates
based on usability feedback conducted to determine what developers
really need help with as they add their own functionality to the app.
Fixed Layout Application
Moving
up the complexity scale, the Fixed Layout Application template is meant
to do just what it says – provide a jumping off point for apps that are
logically fixed layout. The crux of this code is the use of the ViewBox
control in the default.html:
default.html
- <body>
- <div data-win-control="WinJS.UI.ViewBox">
- <div class="fixedlayout">
- <p>Content goes here</p>
- </div>
- </div>
- </body>
Line
2 wraps the content of the app in a ViewBox control, which will scale
everything inside of it to the size of the content, which is defined in
the default.css file with the fixedLayout style:
default.css
- .fixedlayout {
- -ms-grid-columns: 1fr;
- -ms-grid-rows: 1fr;
- display: -ms-grid;
- height: 768px;
- width: 1024px;
- }
You’ll
see in lines 5 and 6 that the height and width of the div contained in
the ViewBox is 768x1024, which means that the content can be created
using absolute positioning and sizing. The job of the ViewBox is as the
app is resized, either the computer’s resolution changes or more likely
the app is moved between landscape, portrait, split and full sizes, the
ViewBox will scale the content to take up as much room as possible,
keeping the aspect ratio constant and scaling the content such that the
app itself can think of itself as logically 768x1024 (or whatever the
top-level div’s size is). This is very handy for building things like
casual games where you want scaling, but generally not flowing – you
want to control where the Scrabble tiles are or the tic-tac-toe pieces
and it’s much easier to do that with a fixed size.
And now that
I’ve described it, I’ll tell you that this template is the only one
that’s structurally identical between BUILD and Beta. Still, it is
useful.
Navigation Application
The next one up the
ladder is the Navigation Application template, which is where we get the
Back button and the support for moving HTML fragments into and out of
the DOM just like the user was logically navigation page-to-page. In the
BUILD bits, this navigation functionality was packaged in the
default.js file, but in the Beta, default.js is just the same as the
simpler templates. Instead, the navigation functionality is packaged
into a new file: navigator.js. The reason this file is separate is to
make it clear if you’d like to implement a different navigation policy,
e.g. MVC, then this is the file to start with. Further, while this
functionality would seem a shoe-in to be included in WinJS, it’s not
quite “baked” enough, which means that MS hasn’t yet decided that this
is “the way” to do navigation.
Still, it’s “a way” to do
navigation in a Metro/JS app and a pretty useful one. Essential the way
it works is that there is a singleton PageControlNavigator in the
default.html file that holds the pages as they’re swapped in. The
default.html is also where navigator.js is included:
default.html
- <script src="/js/navigator.js"></script>
- ...
- <div id="contenthost" data-win-control="Application7.PageControlNavigator" data-win-options="{home: '/html/homePage.html'}"></div>
The
navigator.js file defines the PageControlNavigator control, which holds
the logical pages as the user clicks around in the application. The
home parameter is where to start the navigation. Navigation is to a
Page, which is really a mapping between an HTML file and a set of events
to handle over the lifetime of that Page:
homePage.js
- // This function is called whenever a user navigates to this page. It
- // populates the page elements with the app's data.
- function ready(element, options) {
- // TODO: Initialize the fragment here.
- }
-
- WinJS.UI.Pages.define("/html/homePage.html", {
- ready: ready
- });
Of
course, navigating to the home page is going to be rare compared to
navigating between pages. The easiest way to get a new page to add to
your app is to right-click on your project in the Solution Explorer and
select Add | New Item:

The
last item three item templates on the list are for shell contract
implementations, which are beyond the scope of this blog post, but the
first one is a Page Control, which gives us a triad of HTML, JS and CSS
that fits exactly into the navigation model provided by the
PageControlNavigator control:
page2.html
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>page2</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>
-
- <link href="page2.css" rel="stylesheet">
- <script src="page2.js"></script>
- </head>
- <body>
- <div class="page2 fragment">
- <header aria-label="Header content" role="banner">
- <button class="win-backbutton" aria-label="Back" disabled></button>
- <h1 class="titlearea win-type-ellipsis">
- <span class="pagetitle">Welcome to page2</span>
- </h1>
- </header>
- <section aria-label="Main content" role="main">
- <p>Content goes here.</p>
- </section>
- </div>
- </body>
- </html>
page2.cs
- .page2 p {
- margin-left: 120px;
- }
page2.js
- // This function is called whenever a user navigates to this page. It
- // populates the page elements with the app's data.
- function ready(element, options) {
- // TODO: Initialize the fragment here.
- }
-
- function updateLayout(element, viewState) {
- // TODO: Respond to changes in viewState.
- }
-
- WinJS.UI.Pages.define("/page2.html", {
- ready: ready,
- updateLayout: updateLayout
- });
Navigating to this new control defined by these files is a simple matter of calling the navigate method:
homePage.html
- <a onclick="WinJS.Navigation.navigate('/page2.html')">Page 2</a>
As far as the user is concerned, the anchor tag shows up as a link like any other:

Clicking
on “Page 2” fires the onclick event, which calls the navigate method,
passing in the path to the HTML file and causes the Page control defined
in page2.html, page2.js and page2.css to be loaded:
In
addition to whatever content on your Page control, notice that the Back
button shows up automatically. The Back button manages navigation via
clicking, touching and the browser keys; Ctrl+Left Arrow and Ctrl+Right
Arrow work as Back and Forward respectively.
Grid and Split Application
At
this point, we’ve covered almost all of the core concepts that make up
the Grid and Split applications: they bring in WinJS by reference, they
use controls and they use navigation via the Page controls. In fact,
even though the Grid app has three pages and the Split app has two,
they’re really just the navigation template with the pages to implement
the Grid and Split app patterns that MS decided were the major app
patterns appropriate for Win8. However, the Grid and Split application
templates do have two major features that the other templates don’t
have: support for multiple view states and a centralized data model.
Multiple
view state support means that as the app is moved between portrait,
landscape, full and split, the app adjusts itself to look good in all
states. The view state management is mostly handled with CSS styles
associated with media modes, like in the Split App’s itemsPage.css:
itemsPage.css
- ...
- @media screen and (-ms-view-state: snapped) {
- .itemspage .itemslist .win-vertical.win-viewport .win-surface {
- margin-bottom: 30px;
- }
- ...
In
Metro/JS apps, MS has provided a media query predicate called
-ms-view-state, which can be one of the four view states and the styles
in the media query block will be applied when the app moves to that
state. In addition, if you want to handle the view state change in JS,
you can do so with updateLayout event in your Page control, like this
snippet from itemsPage.js:
itemsPage.js
- // This function updates the page layout in response to viewState changes.
- updateLayout: function (element, viewState) {
- var listView = element.querySelector(".itemslist").winControl;
- if (viewState === Windows.UI.ViewManagement.ApplicationViewState.snapped) {
- listView.layout = new ui.ListLayout();
- } else {
- listView.layout = new ui.GridLayout();
- }
- }
In
this case, the updateLayout event is called when the control is
initially created and as the app moves through the view states so it can
change the layout style for the ListView control showing the contents
of the page:


Landscape vs. Snapped view state layout for the itemsPage ListView control
The
other major feature of the Grid and Split app templates – and this
feature is new in the Beta bits – is the centralized data model, which
is where the data for all pages comes from. This data model is defined
in data.js and it contains the static group and item data as you just
saw. The core of the data is exposed from data.js like so:
data.js
- WinJS.Namespace.define("data", {
- items: groupedItems,
- groups: groupedItems.groups,
- getItemsFromGroup: getItemsFromGroup
- });
These three members of the data object are used throughout the templates, e.g. in the itemsPage.js ready event handler:
itemsPage.js
- // This function is called whenever a user navigates to this page. It
- // populates the page elements with the app's data.
- ready: function (element, options) {
- var listView = element.querySelector(".itemslist").winControl;
- ui.setOptions(listView, {
- itemDataSource: data.groups.dataSource,
- itemTemplate: element.querySelector(".itemtemplate"),
- oniteminvoked: this.itemInvoked.bind(this),
- });
- this.updateLayout(element, Windows.UI.ViewManagement.ApplicationView.value);
- },
Notice
that the data.groups property is used on line 6 to perform a data
binding operation. That data binding is against the dataSource property
of the object returned from data.groups, which itself is created by a
method on the WinJS.Binding.List object that holds the grouped item
data. It’s this binding list, a new feature in WinJS for the Beta, that
makes it easy to move from the static data provided by the templates and
dynamic data that your app defines.
The binding list is a
binding data source, which means that as you add items to it, it
notifies any control that happens to be bound to it. This is especially
handy when your app starts up with zero data, but you need to initialize
the ListViews such that as the data is available (perhaps from an
asynchronous network call), it will be shown.
If you open up the data.js, you’ll see the static sample data:
static sample data
- // Each of these sample groups must have a unique key to be displayed
- // separately.
- var sampleGroups = [
- { key: "group1", title: "Group Title: 1", subtitle: "Group Subtitle: 1", backgroundImage: darkGray, description: groupDescription },
- ...
- ];
-
- // Each of these sample items should have a reference to a particular
- // group.
- var sampleItems = [
- { group: sampleGroups[0], title: "Item Title: 1", subtitle: "Item Subtitle: 1", description: itemDescription, content: itemContent, backgroundImage: lightGray },
- ...
- ];
The
group data has a unique key, a title, a subtitle, a background image
and a description, which are all fields that the data templates used in
the Split and Grid apps depend upon (although you can change them if you
like). The item data has a reference to the group to which it belongs, a
title, a subtitle, a description, a background image and the content
for the item itself.
The code that populates the binding list with the sample data looks like this:
statically bound data
- var list = new WinJS.Binding.List();
- var groupedItems = list.createGrouped(groupKeySelector, groupDataSelector);
-
- // TODO: Replace the data with your real data.
- // You can add data from asynchronous sources whenever it becomes available.
- sampleItems.forEach(function (item) {
- list.push(item);
- });
As
the comment makes clear, it’s this code you’re most likely to want to
change. Instead of pulling in static data from the sampleItems array, we
want to pull the items in asynchronously, perhaps from an RSS feed or two just like my earlier post:
dynamically bound data
- var list = new WinJS.Binding.List();
- var groupedItems = list.createGrouped(groupKeySelector, groupDataSelector);
-
- // RSS feeds
- var feeds = [
- { key: "feed1", title: "Scott Hanselman", subtitle: "a blog", backgroundImage: darkGray, description: "a blog", url: "http://feeds.feedburner.com/ScottHanselman" },
-
- { key: "feed2", title: "Raymond Chen", subtitle: "a blog", backgroundImage: lightGray, description: "a blog", url: "http://blogs.msdn.com/b/oldnewthing/rss.aspx" },
-
- { key: "feed3", title: "Chris Sells", subtitle: "a blog", backgroundImage: mediumGray, description: "a blog", url: "http://sellsbrothers.com/posts/?format=rss" },
- ];
-
- feeds.forEach(function (feed) {
- WinJS.xhr({ url: feed.url }).then(function (request) { processPosts(feed, request); });
- });
-
- function processPosts(feed, request) {
- // parse the RSS
- var nodes = request.responseXML.selectNodes("//item");
- for (var i = 0, len = nodes.length; i < len; i++) {
- var node = nodes[i];
- var item = {
- group: feed,
- title: node.selectNodes("title")[0].text,
- subtitle: node.selectNodes("pubDate")[0].text,
- description: "a post",
- content: node.selectNodes("description")[0].text,
- backgroundImage: feed.backgroundImage
- };
- list.push(item);
- }
- }
In
this case, our group data is a set of RSS feeds, being careful to
continue to use the same group field names so I don’t have to update the
data templates in the rest of the app. When the app loads, I still
create a binding list, but instead of filling it directly, I start an
async xhr call (the WinJS XMLHttpRequest wrapper) for each feed,
creating an item for each RSS post I find upon a successful completion.
Because I’ve left the data model alone and because I’m using the binding
list, that’s all I have to change and now the entire app has been
updated to support that data:

The items page with the set of feeds in the Split app template

The split page with the posts from the selected feed
Where Are We?
As
you can see, the Metro/JS templates in the VS11 beta start simple and
add features with navigation, pages with specific app pattern
functionality, multiple view state support and a unified data model. The
main difference is the Beta versions of this templates is that code has
been simplified, beautified and pushed into WinJS as much as possible
to make the inside of your app just as pretty and easy to use as the
outside.