In Part 1 we learned about creating views, and in Part 2 saw the ProjectionManager API. Now we turn to the Windows.UI.ViewManagement.ApplicationViewSwitcher class, something that’s again demonstrated in the Multiple views sample in the SDK.

Those methods of that class—with some verbose names!—are:

  • switchAsync(id): (3 overloads) Switches to a given view in the same space as the calling one. If the target view is already visible elsewhere on the screen, however, this will simply change focus to that view. A value from ApplicationViewSwitchingOptions can be used to customize the transition: default (standard transition), skipAnimation (no transition), or consolidateViews (closes the calling view).
  • tryShowAsStandaloneAsync: (3 overloads) Shows the new view adjacent to the calling view, with options from ViewSizePreference to determine the desired state of the new and calling views: default, useLess, useHalf, useMore, useMinimum, useNone. You can experiment with these variations in scenario 1 of the sample.
  • disableShowingMainViewOnActivation: Prevents the primary view of the app from showing on subsequent activations, that is, when it’s appropriate to activate the app directly into a secondary view. Showing the primary view is always the default unless this method is called. This is shown in scenario 2 of the sample, with the actual call in js/default.js.
  • prepareForCustomAnimatedSwitchAsync: Tells the views whether to run default animations on a switch; by specifying the skipAnimation option, you can attach a completed handler to this promise to perform custom animations. See scenario 3 of the sample.

Because the details and variations of these APIs get rather complex, I’ll leave it to you to explore the sample directly. Note that in the main scenarios of the app you won’t find any calls to switchAsync—these are made in the secondary view (js/secondaryView.js) to switch back to the primary view. In each case the view closes itself as part of the switch, which isn’t a required behavior, of course.

To show the basic switching behavior, then, I’ve made a few small modifications to a copy of this sample in my second edition companion content. First, the button in the secondary view to switch back to the main view does not close the secondary one. Then I’ve added a button to scenario 1 of the main app to call switchAsync on the selected secondary view. You’ll see how it brings that view up in the same space as the original one, rather than alongside. If you switch back from the secondary view, the main view will appear in that space.

Things get interesting when you create an adjacent view first, then in the main app switch to a secondary view in the space. Then you’ll see two secondary views at once. If you switch to the main app in either, you’ll then find that the Switch to Main View button in the other secondary view just changes focus to the already-visible app. Otherwise you’d be seeing the main app view twice, which would be very confusing!

In summary, I hope that you’ll find some excellent scenarios in which to use multiple views. Given the newness of the feature, you have an opportunity right now for your app to really stand out if you’re an early adopter.


See Part 1 for creating views.

Creating a new view doesn’t actually make it visible—the view’s HTML, CSS, and JavaScript and C#/XAML are all loaded and running, but nothing will have appeared on the screen.

For that you need to use one of two APIs: the ProjectionManager (this part) or the ApplicationViewSwitcher (Part 3 of this post series), both of which are in Windows.UI.ViewManagement.

The ProjectionManager is meant for full-screen scenarios and work with a single secondary view. Its projectionDisplayAvailable property [and I’m going to give the member names in JavaScript casing, so C# readers please translate!], first off, tells you whether projection is possible and, along with the projectiondisplayavailablechanged event, is what you use to enable a projection feature in an app.

To make the view visible you pass its viewId to startProjectingAsync along with the ID of the primary view (the one from ApplicationView.getForCurrentView().id). Later on, call stopProjectingAsync to close the view and swapDisplaysForViewsAsync to do what it implies.

For a simple [JavaScript] example, refer to the SimpleViewProjection example in the companion content for Chapter 8 of my second edition. On startup it gets the primary view and the ProjectionManager (js/default.js):

var view = vm.ApplicationView.getForCurrentView();
var projMan = vm.ProjectionManager;

The Start button in the example is itself enabled or disabled according to the ProjectionManager:

btnStart.addEventListener(“click”, startProjection);

projMan.onprojectiondisplayavailablechanged = function () {
    checkEnableProjection();
​}

function checkEnableProjection() {
    btnStart.disabled = !projMan.projectionDisplayAvailable;
}

When you click Start, the app creates the view and starts projecting, using the id’s of both views:

viewProjection = MSApp.createNewView(“ms-appx:///projection/projection.html”);
projMan.startProjectingAsync(viewProjection.viewId, view.id).done(
function
() {
   
// enable/disable buttons

});

​Other buttons will call stopProjectingAsync and swapDisplaysForViewAsync, and other code handles selectively enabling the UI as needed. There’s also a button to do a postMessage to the projection with the current time.

function sendMessage() {
   
var date = new
Date();
   
var timeString = date.getHours() + “:” + date.getMinutes() + “:”
+ date.getSeconds()
        +
“:”
+ date.getMilliseconds();
   
var
msgObj = { text: timeString };
    viewProjection.postMessage(JSON.stringify(msgObj),
        document.location.protocol +
“//”
+ document.location.host);
}

The projection page is in projection/projection.html with associated .css and .js files. Within its activated handler it retrieves the opener view and listens for the consolidated event (js/projection.js):

var opener = MSApp.getViewOpener();

var thisView = Windows.UI.ViewManagement.ApplicationView.getForCurrentView();
thisView.onconsolidated =
function
() {
    sendCloseMessage();
}

where sendCloseMessage is a function that just does a postMessage with a “close” indicator so the main app can reset its UI. The same thing happens when you click the Close button in the projection, after which it calls window.close.

For another demonstration–which includes C# and C++ variants–refer to the Projection sample in the SDK. It basically does the same thing as the simple example above, adding a little more to set view properties like the title. I didn’t show any code from the sample, however, because it buries the basic API calls like createNewView and getViewOpener deep inside helper classes called ProjectionView.ViewManager (for the primary view) and ProjectionView.ViewLifeTimeControl (for the secondary view) [in the C# version there’s a SecondaryViewsHelper.ViewLifetimeControl class for the same purpose]. These classes s a little too complicated to use as an introduction to the API!

This same mini-framework is also used in the SDK’s Multiple Views sample, which demonstrates the methods of the ApplicationViewSwitcher class, that will be our subject for Part 3.


[The following is taken from Chapter 8 of ​Programming Windows Store Apps in HTML, CSS, and JavaScript, Second Edition/Second Preview​, available at http://aka.ms/BrockschmidtBook2. I’ve added a few notes that I hope will be useful to C# developers, though not working in C# much I can’t give as much detail.]

Many years ago, when I was very actively giving presentations at many developer conferences, I so much wished that Microsoft PowerPoint could present my slides on the main display for the audience while I got a view on my display that showed the next slide as well as my notes. You might be laughing because PowerPoint has had this feature for quite some time (I wasn’t the only one who made the request!). The point, though, is that there are certainly app scenarios where a single app wants to manage multiple independent views, possibly and oftentimes on separate monitors, and the user has the ability to rearrange and resize those views, which includes dragging them between monitors. Any one view, though, is limited to a single display (that is, a view cannot span displays).

Projection scenarios like PowerPoint are clearly one of the primary uses for multiple views; a game might also use a second view for various controls and output windows so they don’t interfere with the main display. A different kind of use is where an app has several independent (or loosely coupled) functions that can operate independently and can benefit from being placed side by side with views from other apps (multitasking at its best!). A customer-management system for a mobile sales rep might have one view for appointments and contacts, another for data entry forms, and a third for managing presentations and media. Although these functions could be part of the same layout within a single app view, they don’t need to be. Having them as separate views—which means they operate on different threads and can only share data via the file system—allows the user to place them in relation to other apps such as a web browser (for customer research) and an email app.

The caveat with multiple views is that they run on separate threads and therefore each have their own script context. Views can only communicate with each other through postMessage calls in JavaScript (as are used to communicate between the local and web contexts), or Dispatcher.BeginInvoke in C#. Views can, however, exchange data via appdata settings and/or files, which they share in common.​

In JavaScript, a view is created through the MSApp.createNewView API, provided by the app host and not WinRTs specific to apps written in HTML and JavaScript. The one argument you give to this method is a string with the ms-appx URI of an in-package HTML page to use for the new view (only ms-appx URIs are allowed, meaning the view runs in the local context). That HTML file can, of course, reference whatever own stylesheets and script (including WinJS) that it needs. All of this will be loaded as part of the createNewView call, even though the view is not yet visible. The usual DOM events like DOMContentLoaded will be raised in the process, and you can use the WinJS.Application events as always (provided that you call app.start() to drain the queue).

The MSAppView object that createNewView returns will have a unique viewId property to identify it, along with postMessage and close methods. The latter is what the app clearly uses to close the view. Within the secondary view, it will receive message through the window.onmessage event, as usual. The new view can also call window.close to close itself, and the user can also close the view with touch/mouse gestures or Alt+F4. As for sending data back to the app, the view calls MSApp.getViewOpener to obtain the MSAppView object for the app’s primary view—its postMessage method will raise a window.onmessage event in the primary view. These relationships are shown below:
View communication

A primary view creates a secondary view through MSApp.createNewView. The secondary view retrieves a reference to the primary view through MSApp.getViewOpener. The result in both cases is an MSAppView object whose postMessage call sends a message to the other view.

The C# analog to MSApp.createNewView is CoreApplication.CreateNewView. This produces a new CoreWindow object, and if you send that to Windows.UI.ViewManagement.ApplicationView.GetApplicationViewIdForWindow, you get the unique viewId. The view can close itself with ​Window.Current.Close()​, and it can access the primary view through App.Current.MainDispatcher (and App.Current.MainViewId).

Let me note up front that if a secondary view closes itself, the app won’t receive any kind of event. Typically, then, the secondary view will inform the app that it’s closing. This is also where the secondary view should subscribe to the ApplicationView.onconsolidated event to detect when the user closes it directly, and post a message to the app. We’ll see examples in later posts.


Events in the DOM are one of those things that you learn to use early on, but without necessarily having a deep understanding. I really appreciated this article from Smashing Magazine on the subject: http://coding.smashingmagazine.com/2013/11/12/an-introduction-to-dom-events/. One of the best parts is its clear description of event capture/target/bubbling phases.


I was following a thread recently where a dev was trying to track down an app crash. In this case he had a window.onerror handler set up but it wasn’t being called.

The bottom line in the thread was that if any exception is thrown within the context of a WinJS.Application event, such as onactivated, then it will be picked up only by a WinJS.Application.onerror handler and not window.onerror. On the other hand, exceptions that are thrown in any other function context, e.g. the callback to a setTimeout or a button click handler, will be picked up by window.onerror as well as by WinJS.Application.onerror, which wraps window.onerror.

Consider the following bit of code in an otherwise blank app project:

(function () {
​   
var app = WinJS.Application;

​   
app.onactivated = function (args) {
​      
throw (“Error from on activated”);
    };

    app.onerror = function (e) {
        console.log(“WinJS.Application.onerror e = “ + e.detail.errorMessage);
        returntrue;
    }

    window.onerror = function (e) {
​       
console.log(“window.onerror e = “ + e)
        returntrue;
​   
}

    app.start();

    throw (“Error outside of WinJS.Application.”);
})();

Running this code, Visual Studio will call out the exception from the last throw. Pressing Continue you’ll get to window.onerror, followed by app.onerror. You’ll then get into app.onactivated, where that thrown exception will then take you to app.onerror but not window.onerror.