JavaScript for Windows Store Apps: View States

Creating an application for the Windows Store requires forethought to a number of considerations – one of which is how will you want your app to appear when seen in different view states.

When your application is running full screen in Windows 8, it will be in either landscape or portrait orientation.  When the orientation is landscape mode, two additional views are possible: snapped or fill.  A snapped view is docked either on the right or left side of the screen, with a width of 320px.  The fill view is the larger remaining portion of the screen when another app is in snapped view. 

Note Snapped and fill options are only available when the screen resolution is a minimum of 1366 x 768 and supporting wide screen (16:9) aspect ratio.

When developing apps using JavaScript, you have two main ways to manage the view states in your apps:  Programmatically via JavaScript, or declaratively with CSS3 Media Queries.  It is recommended that you use media queries to manage view state changes.  However, there are times when you will need to respond to a view state change in code, and that is going to be our focus in this post.

What is Your Current View?

The Windows.UI.ViewManagement namespace provides some classes and enumerations for managing an applications view.  The ApplicationView class can be used to determine the applications current view state by calling the value property.  The return type of value is numeric, and maps to the ApplicationViewState enumeration.  Armed with both, the following code shows a helper method for returning a string with the current view state name:

var appView = Windows.UI.ViewManagement.ApplicationView;
var viewStates = Windows.UI.ViewManagement.ApplicationViewState;

function getViewStateName(viewState) {
    viewState = viewState || appView.value;
    var vs;
    switch (viewState) {
        case viewStates.fullScreenLandscape: // 0
            vs = "FullScreenLandscape";
        case viewStates.filled:              // 1
            vs = "Filled";
        case viewStates.snapped:             // 2
            vs = "Snapped";
        case viewStates.fullScreenPortrait:  // 3
            vs = "FullScreenPortrait";
            vs = "Unknown";
    return vs;

The above code is useful for determining what the current view state is.  What about being notified when a view state change occurs?  One way to accomplish this is by responding to the resizing of the window as seen here:

// manage view state in anonymous handler
window.addEventListener("resize", function(){ }); 

The above line of code would allow you to write code in the anonymous function to query the applications view state and respond accordingly.

If you happen to be using Page Controls you are also likely using the PageControlNavigator, which is a class defined in a navigator.js file included in Visual Studio projects that support single-page navigation model.  Let’s look under the hood of PageControlNavigator, particularly when it responds to the application resizing:

_resized: function (args) {
    // if a page control exists and has updateLayout defined
    if (this.pageControl && this.pageControl.updateLayout) {
            this.pageControl,  // instance of pageControl
            this.pageElement,  // element containing page 
            appView.value,     // current view state
            this.lastViewstate // previous view state
    // capture view state
    this.lastViewstate = appView.value;

The above snippet of code shows what the PageControlNavigator does when it responds to resizing.  The code checks to see if the current page control has defined an updateLayout function, and if it has, it calls it with parameters useful for interrogating.  Now let’s look at an example of an updateLayout function inside a page control:

updateLayout: function (element, viewState, lastViewState) {
    /// <param name="element" domElement="true" />

    // TODO: Respond to changes in viewState.
    pageTitle.innerText = getViewStateName(viewState);

In the example above, an element with the ID of “pageTitle” sets it’s text to equal the response of the helper method shown previously – which returns a string with the current view state name.

Responding to a Different View

Now that we have established where to write code when the view changes, it is now time to focus on what you might do in that response.  Suppose you have a ListView control on the page that displays items in full screen mode like so:


Now when going to snapped view, it looks like this:


Notice in snapped view the scroll bar is still moving horizontally.  What if we want the list to scroll vertically when in snapped view?  This is where a few lines of code can make the difference to improve the user experience.

The ListView has a layout property that allows you to change from a horizontal grid to a vertical list.  When a view state change occurs, the following code conditionally switches the layout:

// viewStates is Windows.UI.ViewManagement.ApplicationViewState;
if (viewState == viewStates.snapped) {
    // vertical scrolling list of data
    list.layout = new WinJS.UI.ListLayout();
} else {
    // horizontal scrolling grid of data
    list.layout = new WinJS.UI.GridLayout();

The code above (written inside the updateLayout function) changes a ListView control with an ID of “list” to switch to a different layout if the view state is snapped, otherwise it reverts to the original grid layout.  Doing this along with some tweaks to CSS via media queries (such as adjusting margins) results in the improved UI when in snapped view:


The content can now be scrolled vertically!

Embrace a Different Point of View

No doubt you will enjoy being a user of applications running on Windows 8.  One of the features that is sure to be used by multi-tasking enthusiasts is running apps in snapped & filled modes.  Make sure you when you develop apps for the Windows Store, you create a compelling UI for each view.  Also make sure to take advantage of all the resources available at Generation App!

    Copyright © Microsoft Corporation. All rights reserved.
    The code provided in this post is licensed under the Microsoft Public License (Ms-PL).
blog comments powered by Disqus