One of the areas that has seen the most change between Windows 8 and Windows 8.1 is the WinJS ListView control. The whole control was basically overhauled from its WinJS 1.0 incarnation. It’s WinJS 2.0 version is much more performant, supports drag and drop, used CSS grid/flexbox for layout rather than absolute positioning, supports more built-in layouts, makes it easy to write custom layouts, and improves keyboard support.

In writing the chapter on collection controls for the second edition of Programming Windows Store Apps with HTML, CSS, and JavaScript, I didn’t want to burden the chapter with describing all the changes–I made the decision early on that the book would really present the state of the platform in Windows 8.1 and talk very little about changes or migration. A blog is better for that!

Toward that end, this post is summarizes all the changes that are documented or that I’ve encountered in writing the book chapter.

First of all, here’s the list of ListView 1.0 features that are deprecated in ListView 2.0, and what replaces them:

  • Incremental loading properties. Incremental loading is handled either through the data source or the item rendering function. The new HTML ListView incremental loading behavior sample (http://code.msdn.microsoft.com/windowsapps/ListView-loading-behaviors-718a4673) shows how, by adding more items to the Binding.List in the item renderer.
    • loadingBehavior=’incremental’
    • automaticallyLoadPages
    • loadMorePages
    • pagesToLoad
  • Backdrops were a feature added late for ListView 1.0 as a band-aid for its performance on ARM devices. Given that ListView 2.0 performs so much better, this feature is often no longer needed, but even so, it’s handled through CSS now. So the following properties are obsolete in favor of the win-backdrop CSS selector in WinJS 2.0:
    • ListLayout: backdropColor, disableBackdrop
    • GridLayout: backdropColor, disableBackdrop
  • The GridLayout’s new orientation property obsoletes its earlier horizontal property. A GridLayout supports both vertical and horizontal orientations.
  • The ListLayout’s vertical property is obsolete in favor of the orientation property, which supports both vertical and horizontal.
  • Cell spanning happens how through the CellSpanningLayout class, obsoleting the GridLayout’s earlier cell-spanning features:
    • itemInfo, groupInfo, and maxRows. In the CellSpanningLayout you’ll find itemInfo, groupInfo, and maximumRowsOrColumns.
  • The ListView’s resetItem and resetGroupHeader methods are deprecated because the control no longer recycles items. In WinJS 1.0, as a performance optimization, a rendering function could receive a second parameter that was an already-created item element tree, in which you’d replace the data. These properties let you centralize the cleanout process, but as recycling is no longer used, these methods do nothing.
  • The earlier IListLayout and related interfaces for custom layouts, which were really never documents, are obsolete. Layout has been overhauled from an absolute positioning model (which introduced many performance issues) to one based on pure CSS. As a result, the custom layout model for WinJS 2.0 is much simpler, using the IListLayout2 and related interface. The HTML ListView custom layout sample shows this (http://code.msdn.microsoft.com/windowsapps/HTML-ListView-custom-9676a187).

It’s good to note that WinJS.Binding.Template controls are compiled by default in WinJS 2.0. If you find a problem with that, the Template object has an option called disableOptimizedProcessing that, when set to true, will impose the WinJS 1.0 interpreted template model.

Other changes to the ListView for WinJS 2.0 introduce new features and capabilities:

  • Invocable headers: groupHeaderTapBehavior and headerInvoked properties.
  • Drag and drop: itemDrag* events, itemsDraggable, itemsReorderable properties.
  • ListView uses maxDeferredItemCleanup property instead of 1000 as the default.
  • ListView implements the WinJS standard dispose pattern and triggerDispose
  • CSS-based layout, which enables easier custom layouts, improves performance quite a bit.

 


[Update: added note that you can specify array and object literals and made slight correction that the control usually calls setOptions, not the parser.]

When declaring a WinJS control in HTML, you specify the control’s constructor in the data-win-control attribute for the host element (typically a <div> but not always), and specify options in the data-win-options attribute. When the control is instantiated through WinJS.UI.process or processAll, WinJS will parse the data-win-options string and pass it to a control’s constructor (which then often calls WinJS.UI.setOptions with the object). This makes a simple way to configure the control declaratively rather than writing JavaScript to do the same thing.

The documentation for data-win-options is pretty basic. It pretty much says that each entry in the string is of the form <property>: <value> with multiple entries separated by commas. This is what we see most often, for instance:

<button data-win-control=”WinJS.UI.AppBarCommand” data-win-options=”{id: ‘accept’, label: ‘Accept’, icon: ‘accept’}”></button>
<div class=”section1″ data-win-control=”WinJS.UI.HubSection” data-win-options=”{header: ‘Images’, isHeaderStatic: true}”>
<div class=”differentRatingColor” data-win-control=”WinJS.UI.Rating” data-win-options=”{averageRating: 3.4, userRating: 4}”>

What we see here are basically just literal values like 4 (integer), 3.4 (float), true (Boolean), and ‘accept’ (string), which are the most common. However, there are other possibilities for values, many of which you can find if you grep the SDK JavaScript samples for “data-win-options”. To summarize:

  • Values can dereference objects, namespaces, and arrays using dot notation or brackets ([ ]’s), or both. [ ] notation supports the use of array literals.
  • Values can be objects surrounded by { }, which is how you assign values to complex properties. Object literals are supported here.
  • Values can be an id of another element in the DOM, provided that the element has an id attribute and is declared earlier in the markup so it’s available when the present control is instantiated.
  • Values can use the syntax select(‘<selector>’) to declaratively reference an element in the DOM (assuming again that it’s already created)

Here are some examples.

Dot notation to reference members of an enumeration or namespace; the latter is common with a ListView control where the data model has a namespace or a namespace with event handlers for app bar commands:

data-win-options=”{ selectionMode: WinJS.UI.SelectionMode.multi, tapBehavior: WinJS.UI.TapBehavior.toggleSelect }”
data-win-options=”{ itemDataSource: DefaultData.bindingList.dataSource }”
data-win-options=”{id: ‘tenDay’, label: ‘Ten day’, icon: ‘calendarweek’, type: ‘toggle’, onclick: FluidAppLayout.transitionPivot }”

Dot notation plus array dereferences (see the Adaptive layout with CSS sample in html/app.html):

data-win-options=”{ uri: ‘/html/current.html’, data: FluidAppLayout.Data.mountains[0].weatherData[0] }”
data-win-options=”{ uri: ‘/html/tenDay.html’, data: FluidAppLayout.Data.mountains[0].weatherData }”

Object notation (commonly used with ListViews to specify its layout object, also showing some dot notation):

data-win-options=”{ layout: {type: WinJS.UI.GridLayout} }”
data-win-options=”{ selectionMode: ‘none’, tapBehavior: ‘none’, swipeBehavior: ‘none’, layout: { type: WinJS.UI.GridLayout, maxRows: 2 } }
data-win-options=”{ itemDataSource: Data.list.dataSource, layout: {type: SDKSample.Scenario1.StatusLayout} }

To declaratively refer to an existing element in the DOM, you have two choices.First is to use the id of the element, that is, the same name that is in that element’s id attribute. Note that you do not make that name a string literal, but specify it directly as an identifier. For example, if somewhere earlier in markup we declare a binding template:

<div id=”smallListItemTemplate” data-win-control=”WinJS.Binding.Template”><!– … –></div>

then we can reference that control’s root element in an options string as follows:

data-win-options = “{ itemTemplate: smallListItemTemplate }”

This works because the app host automatically creates variables in the global namespace for elements with id attributes, and thus the value we’re using is that variable.

The other way is using the select syntax, which is a way of inserting the equivalent of document.querySelector into the options string (technically WinJS.UI.scopedSelect, which calls querySelector). So the previous options string could also be written like this:

data-win-options = “{ itemTemplate: select(‘smallListItemTemplate’) }”

Alternately, if we declared a template with a class instead of an id:

<div class=”templateSmall” data-win-control=”WinJS.Binding.Template”><!– … –></div>

then we can refer to it as follows:

data-win-options = “{ itemTemplate: select(‘templateSmall’) }”

The HTML AppBar control sample in html/custom-content.html and the HTML flyout control sample in html/appbar-flyout.html):

data-win-options=”{ id: ‘list’, type: ‘content’, section: ‘selection’, firstElementFocus:select(‘.dessertType’), lastElementFocus:select(‘.dessertType’) }”
data-win-options=”{ id:’respondButton’,label:’Respond’,icon:’edit’,type:’flyout’,flyout:select(‘#respondFlyout’) }”

The HTML Repeater control sample also uses select to assign a template to the control:

data-win-options=”{ data: Data.samples2, template: select(‘.template’) }

At present, select is the only method that you can use in this way.

 


I finally found an answer to a sticky problem in my book’s Here My Am! app. The problem is that sometimes, on first launch, the Windows.Devices.Geolocation.Geolocator.getGeopositionAsync call fails even when I tap “Allow” in the consent dialog.

That is, in my startup sequence I have this code:

WinJS.Application.onactivated = function (…) {
var locator = new Windows.Devices.Geolocation.Geolocator();
locator.getGeopositionAsync().done(function (geocoord) { … };
}

The problem is that if the Geolocator object goes out of scope while the consent dialog is up, it will cancel the pending getGeopositionAsync operation, sending the error “Canceled” to the error handler just as if I tapped “Block” (though it all works on subseqeuent runs).

The simple solution is to just create the Geolocator outside of the event handler scope. That way the object sticks around and works just fine.

From what I can tell, this isn’t a universal behavior for WinRT objects; for example, in the same app I create a Windows.Media.Capture.CameraCaptureUI object, call captureFileAsync, and let the object go out of scope. This too has a consent prompt, but doesn’t cancel the capture operation.

In any case, it’s a good thing to be aware of–if you see odd behavior like this, try keeping the object in scope.


Apart from how you can protect your app code (in this previous post), there are two other key resources on best practices for writing secure apps. These are the practices for writing apps that are in themselves hardened against hacking through the apps UI itself (as opposed to hacks on the file system and OS):

Developing secure apps (in the documentation, for JavaScript apps): covers whether to trust the data your receiving, use of local/web contexts, script filtering, use of postMessage, use of HTTPS, cross-domain requests, and the sandbox attribute.

Similar and additional tips can be found in Security best practices for building Windows Store apps on the developer blog. This covers app capabilities, using pickers, authenticating users, and validating files and protocols.

 


It’s sometimes unclear to developers that appdata–what’s stored in %localappdata%packages<your package> in folders like LocalState, RoamingState, and TempState–is not dependent on the version of the app that’s using it. By design, app data is maintained across app updates. That is, the act of installing an app update has no effect whatsoever on app data, except when an app has a background task registered for the ServicingComplete trigger and that background task makes changes.

The version of the app and the version of the app data are two separate things: you can have many revs of the app using the same app data structures, so there’s nothing you need to do when upgrading/updating the app. It’s only when you want to change the app data that you then need to version the app data specifically. Here’s what to do:

  1. Even in your first app version, you should be calling Windows.Storage.ApplicationData.SetVersionAsync to assign a version number to your app data as a whole. This becomes important for how the roaming cloud service manages and maintains copies of the app data when a user hasn’t updated every app on every device.
  2. When you’re going to change the appdata version, the second parameter to SetVersionAsync is a function that will be called to migrate from one version to another. This is the trigger to go through an older version of app data (as it might be on disk) and refresh/update the structures. Windows will assume the migration is complete when you return from this. (See scenario 9 of the Application data sample.)
  3. You can call SetVersionAsync in a ServicingComplete background task, but be mindful of the CPU quotas on background tasks if you have a lot of work to do.
  4. You can always maintain per-file or per-settings versioning on your own, without ever changing the overall version number. The danger of this with roaming state, however, is that Windows will assume that all files are the same version, and because the last writer wins, it’s possible that an earlier version of the app on one of the user’s devices will overwrite a newer version of a file on some other device. I think it’s best to avoid adding another layer of complexity to this scene.

In short, apart from a background task, the callback you provide to SetVersionAsync is where you make any updates/changes to app data, and this would typically happen when you launch an app update that knows it’s going to use a new version of state. Before that time, the app data will be the same as before the app was updated.

 

BONUS: a related question to all this is what happens if an app is suspended and terminated, and then updated? Does that terminated state carry through to the next launch? Well, in Windows 8 the previousExecutionState flag gets reset when an update happens; in Windows 8.1, however, it’s preserved, so it is possible for a freshly updated app to be asked to reload session state from a previous version. If this is a problem for your app, either change the state version for the update, or simply check for a flag in your sessionState to determine whether it came from your updated app or a previous version. The latter is a more lightweight solution and won’t affect roaming state versions in the cloud. It’s one good place where even having a distinct version mark in your sessionState can be helpful, as sessionState is never roamed anyway.

 


To determine whether a device supports orientation changes–that is landscape, portrait, landscape-flipped, and portrait-flipped orientations–the simplest way is to just check whether an orientation sensor exists.

Call Windows.Devices.Sensors.SimpleOrientationSensor.getDefault() and if the return value is non-null, there is an orientation sensor.

For details on the APIs, see getDefault, the SimpleOrientationSensor sample, and Quickstart: Determining device orientation.


If you have an app in the Windows Store that you’ve been offering for free, and later convert it to be a paid app, the question is what happens with those customers who acquired it when it was free?

The answer is that app licenses are granted as either full or trial; licenses don’t differentiate paid or free. So once a user has acquired a full license for the app at whatever price, they have that license permanently. Therefore a change in price only affects new customers–existing customers won’t suddenly be asked to pony up some cash for continued use, which is as it should be, and they can continue to reinstall the app freely.

The bottom line is that existing customers keep their existing licenses across app updates. So if a customer has a trial of your v1 app and you make an update to v2 that no longer has a trial, the v1 app will continue to work until the trial expires.

If you have a non-expiring trial or the trial period is not yet expired, a customer can install your v2 under that license. In this case, when you make such a change in your app, be sure that v2 checks for a trial license state and prompts the user for an upgrade and/or disable v2 functionality. You cannot force them to pay, however.

In short, unchecking the trial license in the Store dashboard for your app prevents new trial licenses from being granted, but exiting ones will still work for new app updates.

 


Developers have been concerned for a long time about the different ways that malicious people can try to hack into apps, extend trials, and otherwise rip you off. It’s something that the Windows team is working on more, but if you haven’t seen the post below, it’s good reading for Microsoft’s official stance on the matter:

http://social.msdn.microsoft.com/Forums/windowsapps/en-US/8b3cf68d-897d-4a47-ace0-2c42355bf688/protecting-your-windows-store-app-from-unauthorized-use

Speaking of obfuscation, Preemptive Solutions, for one, has their Dotfuscator for .NET (C# and VB apps) updated for Windows Store Apps, since late last year. See http://www.preemptive.com/products/dotfuscator/overview.

 


One of my few disappointments with the Surface RT that Microsoft gave me to play with last year is that it refuses to add music located on an SD card to my music library. (I’m sure Microsoft has heard the feedback many times by now, so hopefully it’ll be improved.) I encountered this because with a 32GB Surface model, there just wasn’t space to accomodate 19GB of music files on the built-in SSD, hence the add-on SD card.

Fortunately, I finally found a workaround that I’ll get to in a minute. What primarily prompted this post is more of my experience looking through the Windows Store for a media player that could play music directly from the SD card and not depend on it being in the music library.

In the Store, I searched for “Music Player” and got back over 1700 hits, but the top ones shown by relevance were appropriately relevant. Most of the top 10-15 apps have a price tag, so I started clicking through. This gave me a chance to make some observations about writing apps for the Windows Store.

The first thing I noticed almost counts as a cardinal sin: most of the paid apps did not offer at trial! Egads…very unlikely that I’m going to pay for an app just to see if it does what I’m trying to do (get music from an SD card)? Most apps clearly said, as expected, that they access the music library, but not (as yet) having a solution for the SD card problem, I wasn’t about to pay for any app that didn’t explicitly say that it would load music from an arbitrary location.

I did, some months ago, install an app called Metro Media Player (http://apps.microsoft.com/webpdp/app/8ea516f1-eada-4d0e-931c-557878093350) that does allow you to open and play arbitrary media files, but the downside it that it doesn’t (at least in the version I tried) give you an album view of a folder or let you play the folder contents as an album.

So the first lesson here is clearly: remember to offer a trial for a paid app, even if it’s just for a short period of time. And when the trial is installed, remember to appropriately nag the consumer to upgrade to the paid version. I say “appropriately” because you want the consumer to have a good experience of the app, but not ever forget that they’re freeloading. It’s a fine line to walk, but one that will help conversions.

The second observation is that a number of apps didn’t really fill out all the screen shots that you’re allowed to submit. Remember that your app’s page in the Store is the one and only place a consumer can learn about and get a clear sense of what the app does before deciding to purchase/install a trial. Truly, if you’ve spent many days or weeks writing an app, spend a few hours getting good screenshots and writing compelling copy.

With your app description, an important thing to know about the Windows 8.1 Store is that the first sentence or two of your description will surface in the search results. This means that any words in your copy that don’t immediately make a compelling case for your app are wasted words. For example, one app starts its description–which is what shows up on the search results page–with “This is my very first Metro app”. Um, that’s not very compelling to me :). A number of others start with a phrase like “This app” or “This application” which is inherent in browsing the Store.

So even just a simple change from “This app allows you to play music from your music library and sort by artist or title” to “Play music from your music library and sort by artist or title” says the same thing and gives you more words to show. Even so, you can make it more compelling with a little editing: “Enjoy browsing and listening to your music library and pin albums to your start screen” (the latter idea is in the second sentence, but doesn’t show on the 8.1 Store search results). Every word counts!

I highly recommend finding a friend or associate to help write and edit your copy–anyone who is not yourself can more readily take the viewpoint of a potential customer rather than a developer.

I did eventually install one app that looked promising, and was free, but limited itself to the Music Library. So no progress in solving my problem.

Then I came across Groove: Smart Music Player (http://apps.microsoft.com/webpdp/app/949988e3-de86-4e4e-9039-b261fdc56fd9). It didn’t have the open-a-folder capability I was looking for, but it did contain a note with a link to a blog post about how to get your SD card in your music library (and photos and videos). And with that solution I could get this app–and even the built-in Music app–to work with my SD card.

What I appreciated most is that Groove clearly understood and recognized an issue that many people have, it seems, and offered a solution right there on the Store page. Nice job of customer awareness and empathy!

To the solution now–see http://bit.ly/UrF44P for a process to mount an SD card to empty folder on the Surface’s primary drive through Disk Management, which can then be added to the libraries. To summarize:

  1. From the desktop (Windows Explorer), create a folder somewhere on the primary drive, e.g. c:sd or c:users<your name>sd. Doesn’t matter where.
  2. Hit Win+X and select Disk Management.
  3. Right click (or tap-hold) the SD card and select “Change Drive Letters and Paths” from the menu.
  4. In that dialog, tap “Add…”, select “Mount in the following empty NTFS folder”, and enter the path to the empty folder you created. Then OK out of the dialogs.
  5. Make sure that the folder names on the SD card match the library names under c:users<your name>. If your library is “My Music” make sure that your music on the SD card is in a “My Music” folder. Don’t know why this is needed, but it was essential for me.
  6. Back in Windows Explorer, select the Music Library, on the Library Tools/Manage ribbon tap the Manage Library button, then tap Add… and navigate to the mounted folder on c: with the appropriate media, e.g. c:users<your name>SDMy Music.
  7. Give Windows a little time to index the thing, and voila! Problem solved.

 


Typically, when a user rotates an accelerometer-equipped device, Windows will rotate the display to the nearest quadrant (landscape, portrait, landscape-flipped, and portrait-flipped) and apps will receive a resize event in which they can adjust their layout.

Some apps, however, prefer to keep their layout as-is, regardless of device rotation. A full screen video player, for example, wants to remain in landscape irrespective of the device orientation, allowing you to watch videos while laying sideways on a couch with a tablet propped up on a chair!

Locking the orientation can be done in two places. First, you can specify the orientations the app supports in the app manifest under Supported Rotations on the Application UI tab:

sidebar (preferred orientations)

By default, all these options are unchecked which means the app will be resized (and thus redrawn) when the device orientation changes (and checking all of them means the same thing). When you check a subset of the options, the following effects apply:

  • If the device is not in a supported rotation when the app is launched, the app is launched in the nearest supported rotation. For example, if you check Portrait and Landscape-flipped (I have no idea why you’d choose that combination!), and the device is in Landscape mode, the app will launch into Portrait.
  • When the app is in the foreground, rotating the device to a non-supported orientation has no effect on the app.
  • When the user switches away from the app, the device orientation is restored unless the new foreground app also has preferences. Of course, it’s likely that the user will have rotated the device to match the app’s preference, in which case that’s the new device orientation.
  • When the user switches back to the app, it will switch to the nearest supported rotation.
  • In all cases, when the app’s preference is in effect, system edge gestures work relative to that orientation, that is, the left and right edges relative to the app’s orientation.

You can achieve the same effects at runtime—changing preferences dynamically and overriding the manifest—by setting the autoRotationPreferences property of the Windows.Graphics.Display.DisplayInformation object (this is the one you use in Windows 8.1; in Windows 8, use the DisplayProperties object instead). The preference values come from the DisplayOrientations enumeration, and can be combined with the bitwise OR (|) operator. For example, here are the bits of code (JavaScript) to set a Portrait preference and the combination of Portrait and Landscape-flipped (Windows 8.1):

var wgd = Windows.Graphics.Display;
wgd.DisplayInformation.autoRotationPreferences = wgd.DisplayOrientations.portrait;
wgd.DisplayInformation.autoRotationPreferences = wgd.DisplayOrientations.portrait | wgd.DisplayOrientations.landscapeFlipped;

Note that orientation preferences set in the manifest and through the autoRotationPreferences property do not work with non-accelerometer hardware, such as desktop monitors and also the Visual Studio simulator. The rotations that the simulator performs happen in a different way than those induced by a real accelerometer. To really test these preferences, in other words, you’ll need a real device equipped with that sensor.

To play around with these settings, refer to the Device auto rotation preferences sample. Its different scenarios set one of the orientation preferences so you can see the effect when the device is rotated; scenario 1 for its part clears all preferences and restores the usual behavior for apps. You can also change rotation settings in the manifest to see their effects, but those are again overridden as soon as you change the preferences through any of the scenarios.