[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.


One Comment

  1. Posted November 28, 2013 at 7:00 am | Permalink

    My main gotcha initially was the very first time I connected to a display, my Surface by default was set to mirror (instead of extend): that kind of scenario confuses the app. I added multiple views to my app, and thought my code was really buggy. It worked much more sensibly when the setting is “extend”.

2 Trackbacks

  1. [...] Part 1 for creating [...]

  2. [...] Part 1 we learned about creating views, and in Part 2 saw the ProjectionManager API. Now we turn to the [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>