As of last week I assumed management and content development for the Windows App Builder’s Blog, which I’m sure most of you follow already.

What I’d love to hear from you is this: what content would you like to see on the blog? What questions are you dying to have answered? What ‘inside stories’ from the Windows engineering team would you like to know? Let me know in the comments!


Question: What data type does one use to pass a JavaScript Error object to a WinRT component?

Answer: None, actually. You cannot directly pass an Error object to native code in a component, as that object type won’t be meaningful in C++. You could stringify the Error and pass it as JSON, but that’s something of a pain.

What you can do instead is to source an exception in C++ (or C#), where those exceptions have known HRESULTs, because then you’ll get the appropriate errors in JavaScript thanks to the projection layer. It does take a little extra time (very small) to marshal this exception across the layer boundaries, but would only matter if you end up throwing millions of exceptions per second. (I hope that’s not the case!)

Here’s a C++ example to generate an Access Denied (E_ACCESSDENIED) that’s usable across the component boundary:

class ErrorHelper
{
public:
static void ThrowAccessDenied();
}

ErrorHelper::ThrowAccessDenied()
{
throw ref new Platform::AccessDeniedException();
}

And clearly you can extend ErrorHelper to include other methods for additional errors you need to use.

Thanks to Rob Paveza for this solution.

 


The Semantic Zoom control in WinJS, as you probably know, is basically a control that provides a switching effect between two other controls. Any control that implements the IZoomable interface will work, though in WinJS the only two that do this are the ListView and the Hub. (Implementing the interface is not difficult, though; refer to the HTML SemanticZoom for custom controls sample in the SDK.)

When hosting ListView controls (the most common case), the question can arise about how to size and position the zoomed out view, primarily because the ListView is hosted inside the SemanticZoom control, which sets the position of the ListView itself.

The trick in this case is to have the SemanticZoom control sized to 100% of the desired space, and then use the margins of the .win-surface style on the ListView. The SemanticZoom will honor those margins in its positioning work. Be sure, also, to adjust the height of the .win-surface style as well to prevent scrollbars from appearing when you set the margins.

 


A few Q&A bits for the WinJS ListView (WinJS 1.0 and 2.0)

Q: I've implemented a VirtualizedDataSource that retrieves RSS items from a feed, and this source is bound to a ListView. How do I change an items color or other attribute without reloading the whole list?

A: The key to dynamic data binding for any value is to make sure it's observable. This is the purpose of the WinJS.Binding.as method, which will create add observability to any object.

Q. How do I programmatically select items in a ListView?

A. This is done through the ListView's selection property. This is an object with an interface called ISelection, which just means that the object has those methods. (We refer to an interface in this way for JavaScript objects because there's not a discrete class to refer to otherwise.) These methods include add, clear, set, remove, and selectAll. By changing the state of this object you change the ListView's selection.

Q. Is it possible to change a ListView item's checkmark character?

A. The default checkmark is character uE081 within the item container. There isn't a way to directly change it, however, so you basically have to hide the existing checkmark and add you own:

/* Configure your own */
.win-selection-checkmark::before {
    content: 'E0A5'; /* Your character here */;
    color: red; /* Whatever color your want*/
    font-size: 30px; /* Whatever is appropriate */
}

/* Hide the default */
.win-selection-checkmark {
    color: transparent; /* Make the default disappear */
    font-size: 0px; /* Size it to zero so it doesn't affect layout */
}

To close this series, I wanted to share a few additional bits related to webview, but not necessarily related to one another!

First, in the previous post I showed how to wrap some of the webview’s capture methods in a promise. The same thing is easy to do with invokeScriptAsync, where the promise is fulfilled with the value returned from the webview’s script:

functon callWebviewScript(webview, targetFunction, argsIn) {
return new WinJS.Promise(function (cd, ed) {
var op = webview.invokeScriptAsync(targetFunction, argsIn);

        op.oncomplete = function (args) {;
//Return value from the invoked function (always a string) is in args.target.result
cd(args.target.result);
};

op.onerror = function (e) { ed(e); };
op.start();
});
}

This kind of structure helps you remember the necessary call to start at the end.

With invokeScriptAsync, be aware that the result you pass back must be a string, otherwise you’ll get an empty string.

In the callWebviewScript function above, note that targetFunction can be set to “eval” and argsIn to whatever script string you want to evaluate–meaning that the webview doesn’t necessarily have to have a named function inside it. Just remember that the result of that eval must again be a string.

The next little tip is just knowing that webview cache cookies and other content just like the browser, even if you remove the webview from the DOM and let it get garbage collected. There aren’t facilities to clear information that’s cached in the webview, though you might be able to achieve this through the Windows.Web.HttpClient API instead.

Lastly, the webview has a characteristic that if you overlay another element on a webview that has 100% opacity, the webview will go black as it fails “layer candidacy” as it’s called. The same thing happens with an overlay element with 0% opacity. (See http://msdn.microsoft.com/en-us/library/jj680148(v=vs.85).aspx under “Unsupported Scenarios” section for the description of scenarios where it fails layer candidacy.)

If, however, the overlay element’s style has an opacity of anything other than 1 or 0, like 0.9999 or 0.0001, then the webview is happy. It’s an odd behavior, but a good one to know about.


One of the key feature of the webview that really sets it apart from the iframe is the ability to capture its content, something that you simply cannot do with an iframe. There are three ways this can happen.

First is the src attribute. Once the webview has navigated (and fired its MSWebViewNavigationCompleted event), src will contain a URI to the content as the webview sees it. For web content, this will be an http[s] URI, which can be opened in a browser. Local content (loaded from strings or app data files) will start with ms-local-web, which can be rendered into another webview using navigateToLocalStream. Be aware that while navigation is happening prior to MSWebViewNavigationCompleted, the state of the src property is indeterminate; use the uri property in those handlers instead.

Second is the webview’s captureSelectedContentToDataPackageAsync method, which reflects whatever selection the user has made in the webview directly. The fact that a data package is part of this API suggests its primary use: the share contract. From a user’s perspective, any web content you’re displaying in the app is really part of the app. So if they make a selection there and invoke the Share charm, they’ll expect that their selected data is what gets shared, and this method lets you obtain the HTML for that selection. Of course, you can use this anytime you want the selected content—the Share charm is just one of the potential scenarios.

As with invokeScriptAsync, the return value from captureSelectedContentToDataPackage­Async is again a DOM-ish object with a start method that you must call to perform the operation. If you want to wrap this in a promise, you can use a structure like this:

function captureWebviewSelectionAsync(webview) {
//Wrap the capture method in a promise
return new WinJS.Promise(function (cd, ed) {
var op = webview.captureSelectedContentToDataPackageAsync();
op.oncomplete = function (args) { cd(args.target.result); };
op.onerror = function (e) { ed(e); };
op.start();
});
In this case, the result you care about us args.target.result in the oncomplete event, which is a Windows.ApplicationModel.DataTransfer.­DataPackage object as used with the Share charm. Calling its getView method will produce a DataPackageView whose availableFormats object tells you what it contains. You can then use the appropriate get* methods like getHtmlFormatAsync to retrieve the selection data itself. Note that if there is no selection, args.target.result will be null, so you’ll need to guard against that. Here’s some code, for instance, to copy the selection from one webview to another, using the function above:

function captureSelection() {
var source = document.getElementById(“webviewSource”);
var promise = captureWebviewSelectionAsync(source);

//Navigate the output webview to the selection, or show an error
var output = document.getElementById(“webviewOutput”);

promise.then(function (dataPackage) {
if (dataPackage == null) { throw “No selection”; }

var view = dataPackage.getView();
return view.getHtmlFormatAsync();
}).done(function (text) {
output.navigateToString(text);
}, function (e) {
output.navigateToString(“Error: ” + e.message);
});
}

Note that the captured selection is an HTML clipboard format that includes the extra information at the top before the HTML from the webview. If you need to extract just the straight HTML, you’ll need to strip off this prefix text up to <!DOCTYPE html>.

Generally speaking, captureSelectedContentToDataPackageAsync will produce the formats AnsiText, Text, HTML Format, Rich Text Format, and msSourceUrl, but not a bitmap. For this you need to use the third method, capturePreviewToBlobAsync, which again has a start method and complete/error events. The results of this capture (in args.target.result within the complete handler) is a blob object for whatever content is contained within the webview’s display area. Here’s another function to wrap that operation in a promise:

function captureWebviewBitmapAsync(webview) {
return new WinJS.Promise(function (cd, ed) {
var op = webview.capturePreviewToBlobAsync();

op.oncomplete = function (args) {
var ras = Windows.Storage.Streams.RandomAccessStreamReference;
var bitmapStream = ras.createFromStream(args.target.result.msDetachStream());
cd(bitmapStream);
};

op.onerror = function (e) { ed(e); };
op.start();
});
}

The result of the promise generated by this function is a blob, which you can use for a number of purposes. If you want to display it in an img element, you can use URL.createObjectURL on this blob directly. This means you can easily load some chunk of HTML in an offscreen webview (make sure the display style is not “none”) and then capture a blob and display the results in an img. Besides preventing interactivity, you can also animate that image much more efficiently than a full webview, applying 3D CSS transforms, for instance. You can also stream the blob in an upload, save it to a file, and so forth.

For other purposes, like the Share charm, you can call this blob’s msDetachStream method, which conveniently produces exactly what you need to provide to a data package’s setBitmap method. This is demonstrated in scenario 7 of the SDK’s HTML Webview control sample (though the sample neglects to use the datarequested event’s deferral correctly).

In part 3 I’ll share a few other closing bits on webview.


In Windows 8, an app written in JavaScript could host other HTML content–both local (in-package) and remote (http[s])–in an iframe element. In Windows 8.1, an iframe is still completely supported for in-package content (ms-appx-[web] URIs), but only supports secure remote content (https). For general hosting of web content (http), apps should be using the x-ms-webview element.

In this post and the few that follow, I wanted to share a few details about migrating code from iframe to webview. For a broader discussion of hosting web content, refer to Chapter 4 of my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition. Also see What’s New in Webview for Windows 8.1 on the Windows App Builder’s blog.

For in-package content using ms-appx-[web] URIs, you can continue to use iframes. If you want to switch to webview for any reason with ms-appx-web (you can’t use webview with ms-appx), then you should be able to make a straight change from <iframe src=”…”> to <x-ms-webview src=”…”>. Then you need to change any uses of postMessage to communicate with the iframe to webview.invokeScriptAsync (to call methods in the webview’s script) and the MSWebViewScriptNotify event (to pick up events raised from within the webview using window.external.notify).

For web content, the story gets a little trickier. If you try to direct an iframe in Windows 8.1 to an http:// address, you’ll get a message like this:

APPHOST9625: Unable to navigate to: ‘http://www.mysite.com/’. An iframe attempted to navigate to a URI that is not included in the ApplicationContentUriRules for this app. Use a x-ms-webview element to view the URI instead, or add the URI to the ApplicationContentUriRules section of the package manifest so that the iframe can navigate to it. (In Visual Studio, add this URI to the Content URIs tab of the Manifest Designer.)

Like it says, an iframe in 8.1 must use https for remote content, and then the app’s manifest must have an entry for that site on its Content URIs tab. So if you can use https:// for that site, then you can continue to host it in an iframe. If not, then, you need to use a webview.

With a webview, however, window.external.notify (to raise events from the webview) will work only when src is set to an https:// (and you have a content URI in the manifest) or ms-appx-web::// URI, but not http://.

That said, the webview element can be loaded from alternate source, which is one of the reasons why we have it. For one, you can also use ms-appdata URIs for a webview, either through its src attribute or its navigate method. This makes it possible to download content from the web or generate it dynamically, then render it within the webview. The caveat, however, is that with ms-appdata URIs, you can use invokeScriptAsync but not window.external.notify.

That said, if you load content into a webview using its navigateToString or navigateToLocalStreamUri methods, then you can also use window.external.notify. This means that if you want to load up downloaded or dynamically-generated content into a webview and have it raise events, then you either need to load the content into a memory string and call navigateToString, or you create a local stream provider (refer to the HTML webview control sample for a demonstration, as well as http://blogs.windows.com/windows/b/appbuilder/archive/2013/07/17/what-s-new-in-webview-in-windows-8-1.aspx).

In part 2 we’ll look at capturing webview content.


A while back I worked with a forum question that asked whether the canvas element’s ImageData property for Windows Store apps had this interface:

interface ImageData {
readonly attribute unsigned long width;
readonly attribute unsigned long height;
readonly attribute CanvasPixelArray data;
}

Or this one:

interface ImageData {
readonly attribute unsigned long width;
readonly attribute unsigned long height;
readonly attribute Uint8ClampedArray data;
}

Where ImageData comes from:

var imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);

This was in regards to some pixel manipulation methods using the Uint8ClampedArray.

The answer is that for Windows 8/8.1 and current IE implementations, the canvas provides a CanvasPixelArray. To be honest, the performance difference between the two matters most if you’re just measuring how quickly you can access the pixels. In practice, if you’re doing any meaningful manipulation on each pixel, that computation is probably much more significant.

For pixel manipulation, it does make sense to get the pixels into a WinRT component written in C++. Here, it is possible to pass a CanvasPixelArray to a WinRT component that accepts a byte array, wherein the whole thing will be faster than using a clamped array to begin with. Here’s an example:

void Class1::CreatePattern(WriteOnlyArray<uint8>^ data, int canvasWidth, int canvasHeight)
{
uint32* data32 = (uint32*)data->Data;
for (int y = 0; y < canvasHeight; ++y)
{
for (int x = 0; x < canvasWidth; ++x)
{
uint8 value = x * y & 0xff;
data32[y * canvasWidth + x] =
(255   << 24) |    // alpha
(value << 16) |    // blue
(value <<  8) |    // green
value;             // red
}
}
}
 


When working with the Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList, it’s important to know that it has a 1000 file limit. This has presented a challenge to some developers working with libraries that contain many more files than that, when they try to save every file in the library in this list. Of course, the problem is solved easily by saving the parent StorageFolder in the list instead, which will then include all those files. Sometimes, however, you might want to save a handful of files directly for performance reasons–files that you know you’re going to want, so you don’t have to go through the folders each time.

I’ll mention in this context that I’ve seen discussions about this sort of thing where developers talk about file paths and so forth. When working with files and folders in WinRT, always remember that the StorageFile and StorageFolder objects (and their shared StorageItem base class) are abstractions for path names and should be what you use whenever you think about path names. The key reason for this is that file-like entities can be backed by non-local providers such that the concept of a “pathname’ doesn’t even exist. The StorageFile/Folder/Item abstractions let the provider worry about the mapping details. For the consuming app, then, you use the FutureAccessList to do the equivalent of saving pathname strings in some other local storage. (The same goes for the recently used list that exists alongside FutureAccessList.)

Equally interesting is the question of what happens if files are moved on the file system between when you save a StorageFile to the FutureAccessList and when you later retrieve it. Generally speaking, Windows does its best to track changes to the file system and update the FutureAccessList accordingly, so the bottom line is that you should not worry about it. Of course, if you attempt to open a file obtained from the FutureAccessList, it can fail for any number of reasons, including the file having been moved without the system being able to track it. You have to handle all such exceptions anyway, so an orphaned file is just one in the mix.

 


One of Microsoft's evangelists working with students put together this list of common certification issues.

  • Make sure all your views work. On Windows 8, this means snapped and filled views along with portrait. On Windows 8.1, this means handling variable view sizes down to 500px, and possibly to 320px if you set that flag in your manifest.
  • If you use sounds in your app, make sure there's a clear way to turn them on and off, or set the volume (between 0 and full).

    • It's possible that the manual tester might not see the option in your Settings, so you might need to put a control on canvas if it won't get in the way (and that button can open settings, of course.)
  • Privacy statement

    • If you have ads, you need a privacy statement in your Help or other settings where the tester can see it.
  • Country/Age Rating

    • Make sure to pick your countries carefully: there are cultural differences that will allow/disallow various metaphors and imagery. The author of this list said that one of his apps with "kisses" in it was disallowed in some countries.
    • Age rating: be sure to study the requirements here, as this is a common stumbling point.
  • Logo graphics

    • Never, ever upload an app with the default Visual Studio logos and splash screen. Hopefully the WACK is catching these by now, but I don't want to see any more apps in the Store with the default graphics!
  • Test on different devices and in the simulator

    • If the simulator hangs on launching your app, there's a definite problem.
    • Use the simulator to test orientation changes and all view states on all canonical screen sizes.
    • If you have access to different devices, including Windows RT devices, by all means try them out there too. You'll get a various of scaling factors and screen dimensions.