Bing Maps for Metro Gotcha

July 6, 2012 at 4:12 pm | Posted in Metro, Visual Studio 2011, Windows 8 | Leave a comment

Just ran into a mysterious behavior when trying to use the Bing Maps API for C#/XAML Metro applications. I have several apps that use this API and seem to be working well. This morning, I tried to make another test app and Visual Studio said it could not render the map. The error message indicated that the class was not registered. I doubled checked that the Build configuration was set to Debug with a specific processor type and that I had the Bing Maps and C++ runtime in my resources. I cleaned the solution and rebuilt it with no success.

Finally, I deleted the Bing Maps resource from the solution. When I re-added it, the problem cleared.

(An update: Another solution that I had given up on before discovering this trick suddenly started working after closing and restarting Visual Studio.)

This is one thing that I dislike about XAML development. There is a lot of magic that is going on behind the scenes. It appears that if things are not just so, the solution can break. Fragile. Reminds me of the early days of XAML/WPF in Visual Studio (maybe even for WinForms, I don’t know) but there were times that you could screw up a name of something in your project and the designer would go nuts. No amount of rework would recover. The only recourse was to start over with a fresh template and carefully reconstruct the project piece by piece.

Advertisements

Minimal ListView Binding

May 9, 2012 at 7:51 am | Posted in HTML/JavaScript, Metro, Visual Studio 2011, Windows 8 | Leave a comment

Sometimes it is hard to see the forest for all of the trees. In learning the HTML5/JavaScript platform, I’ve relied on the plumbing of the Blank Application template in Visual Studio without understanding all of the functions. I recently responded to a forum query with an example of binding and updating a ListView with a super simple JavaScript that did not use the template.

This code has a ListView and a Button. The ListView is initialized from an array using a Binding.List. The bindings are declared in the markup. The Button click event triggers the addition of a new item to the list.

<body>
    <div id="myTemplate" data-win-control="WinJS.Binding.Template">
        <div data-win-bind="innerText: id"></div>
    </div>
    <button id="add">Add</button>
    <div id="myListView" data-win-control="WinJS.UI.ListView" data-win-options="{itemDataSource: Dataex.itemList.dataSource, itemTemplate:select('#myTemplate')}">
    </div>
</body>
(function () {
    "use strict";

    var dataArray = [{ id: "one" }, { id: "two" }]
    var dataList = new WinJS.Binding.List(dataArray);

    var p ={itemList: dataList};
    WinJS.Namespace.define("Dataex", p);

    function addItem() {
        dataList.push({ id: "three" });
    }

    WinJS.Utilities.ready(function () {
        document.getElementById("add").addEventListener("click", addItem, false);
        WinJS.UI.processAll();
    });

})();

Simple data binding example

April 30, 2012 at 10:06 am | Posted in HTML/JavaScript, Metro, Windows 8 | Leave a comment

{Code updated to reflect changes in Release Preview.}

I was trying add a simple piece of markup that had text elements bound to an object, but just could not get it to work the way I wanted, i.e. declare a binding source in the markup. By looking at the samples, I could use WinJS.BindingAll(element, object), but for some reason failed with data-win-bindsource in the markup. Finally, I did a Google search on “data-win-bindsource” and ran across a post in November 2011 that was exactly what I was trying to do. It turns out that the answer provider was me!

So for the sake of others who are trying to do the same thing and for pounding this nugget into my own brain, here is the example:


<body>
    <div class="fixed-layout">
        <div data-win-bindsource="mySpace.data">
            <div data-win-bind="innerText: x"></div>
        </div>
        <button id="myButton">
            Click</button>
    </div>
</body>


(function () {
    "use strict";
    var person = {
        name: "Tom",
        city: "Boston"
    }

    var labelSource = WinJS.Binding.as(person);
   
    WinJS.strictProcessing();

    WinJS.Utilities.ready(function(){
        WinJS.UI.processAll().then(function () {
            var elem = document.querySelector("#complexLabel");
            WinJS.Binding.processAll(elem, labelSource);
        });

        var lab = document.getElementById("complexLabel");
        document.getElementById("action").addEventListener("click", changeLabel, false);

    });
   
    function changeLabel() {
        labelSource.name = "John";
        labelSource.city = "New York";
    }

    //Make names public with namespace so that HTML file can see them
    WinJS.Namespace.define('test', {
        labelSource: labelSource
    });
})();

Reading a text file from the app package

April 23, 2012 at 5:37 pm | Posted in HTML/JavaScript, Metro, Windows 8 | Leave a comment
Tags:

This is an example of how to read a text file that is embedded in the app package.

 //Read a text file in the 'data' folder in the app package.
    //Outputs the contents to the console
    function getDataFromPackage(fileName) {
        var myPackage = Windows.ApplicationModel.Package.current;
        var instLocation = myPackage.installedLocation;
        var path = "data\\" + fileName;
        instLocation.getFileAsync(path)
        .then(function (file) {
            return Windows.Storage.FileIO.readTextAsync(file);
        }).done(function (myText) {
            console.log(myText);
        });
    }

Background task pollution

April 22, 2012 at 1:21 pm | Posted in HTML/JavaScript, Metro, Windows 8 | Leave a comment

I am developing a Metro HTML/JavaScript application which uses a background task to notify the user of updates to some data that is collected periodically. Initally, the background task simply read the data, did some filtering and sent a tile notification. This all seemed to be working well. When I added a toast notification; however, I began to see some strange behavior.

First, I noticed that when the background task fired based on a timer, that dozens of processes seemed to appear in the Visual Studio debugger. Second, I found that the toast was triggered multiple times for each interval. Of course, this continued even if the program was no longer running. It occurred after a reboot also.

My suspicion was that the background task was registered multiple times. My program was configured to register the background task every time it was launched. I assumed that the system would just overwrite the previous registration with the new one. It appears, though that each registration is added to a list of registrations even if they are identical. After numerous debug sessions, these registrations were adding up. I was polluting the background task manager.

The programmatic solution to this problem is to unregister all of the tasks associated with the program using the following routine:

function unregisterBackgroundTasks(taskName) {
        //
        // Loop through all background tasks and unregister any with the taskName
        //
        var iter = Windows.ApplicationModel.Background.BackgroundTaskRegistration.allTasks.first();
        var hascur = iter.hasCurrent;
        while (hascur) {
            var cur = iter.current.value;
            if (cur.name === taskName) {
                cur.unregister(true);                
            }
            hascur = iter.moveNext();
        }
    }

This seems to work well but I do not know if there is a way to clear this “pollution” of the background task manager outside of the program except that background tasks are unregistered when a program is uninstalled.

Updating Metro tiles in the background periodically

April 20, 2012 at 9:00 am | Posted in HTML/JavaScript, Metro, Windows 8 | 3 Comments

This is an example of how to use a background task to update an app’s tiles.

First, here is a default html file with a button and status line.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>HelpTileUpdate</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet">
    <script src="//Microsoft.WinJS.0.6/js/base.js"></script>
    <script src="//Microsoft.WinJS.0.6/js/ui.js"></script>

    <!-- HelpTileUpdate references -->
    <link href="/css/default.css" rel="stylesheet">
    <script src="/js/default.js"></script>
</head>
<body>
    <button id="startService">Start Background</button>
    <div id="status">Status of service</div>
</body>
</html>

Next, the default.js which handles the button click event.   This handler requests to use the lock screen (required for timer background tasks) and then registers the task with a timeTrigger set for 15 minutes (the minimum allowed interval).

// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
    "use strict";

    var app = WinJS.Application;

    app.onactivated = function (eventObject) {
        if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
            if (eventObject.detail.previousExecutionState !== Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            WinJS.UI.processAll().then(function onComplete(processedElements) {
                document.getElementById("startService").addEventListener("click", beginBackgroundService, false);
        });
        }
    };

    app.oncheckpoint = function (eventObject) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // eventObject.setPromise().
    };

    app.start();

    function beginBackgroundService() {

        requestLockScreenAccess();
        registerBackgroundTask();
    }

    function displayStatus(msg) {
        document.getElementById("status").innerText = msg;
    }

    function registerBackgroundTask() {
        var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
        builder.name = "myTask";
        builder.taskEntryPoint = "backgroundtask.js";
        var timeTrigger = new Windows.ApplicationModel.Background.TimeTrigger(15, false);
        //var timeTrigger = new Windows.ApplicationModel.Background.SystemTrigger(Windows.ApplicationModel.Background.SystemTriggerType.timeZoneChange, false);
        builder.setTrigger(timeTrigger);
        var conditionType = Windows.ApplicationModel.Background.SystemConditionType.internetAvailable;
        var taskCondition = new Windows.ApplicationModel.Background.SystemCondition(conditionType);
        builder.addCondition(taskCondition);
        var backgroundTaskRegistration = builder.register();

    }

    //
    // This is a helper function to add your app to the lock screen.
    // Time events require the app to be on the lock screen to fire
    //
    function requestLockScreenAccess() {
        var Background = Windows.ApplicationModel.Background;

        //
        // An app can call the add or query API as many times as it wants; however, it will only present the dialog box to the user one time.
        //
        Background.BackgroundExecutionManager.requestAccessAsync().then(function (result) {
            switch (result) {
                case Background.BackgroundAccessStatus.denied:
                    displayStatus("This app is not on the lock screen.");
                    break;

                case Background.BackgroundAccessStatus.allowedWithRealTimeConnectivity:
                    displayStatus("This app is on the lock screen and has access to Real Time Connectivity.");
                    break;

                case Background.BackgroundAccessStatus.allowedWithoutRealTimeConnectivity:
                    displayStatus("This app is on the lock screen, but does not have access to Real Time Connectivity.");
                    break;

                case Background.BackgroundAccessStatus.unspecified:
                    displayStatus("The user has not yet taken any action. This is the default setting and the app is not on the lock screen.");
                    break;
            }
        }, function (e) {
            displayStatus(e);
            console.log(e);
        });
    }
})();

Next, you will need to add a backgroundtask.js file to your project. This code simply checks the date and writes it to a wide tile.

//Background task
//Checks for new events and notifies user.
//Updates tiles

(function () {
    "use strict";

    importScripts("//Microsoft.WinJS.0.6/js/base.js");

    //Begin task
    var backgroundTaskInstance = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current;

    var notifications = Windows.UI.Notifications;

    var date = new Date();

    displayTileNotification(date);
    backgroundTaskInstance.succeeded = true;
    close();

    function displayTileNotification(content) {
        // get a filled in version of the template by using getTemplateContent
        var tileXml = notifications.TileUpdateManager.getTemplateContent(notifications.TileTemplateType.tileWideText01);

        // get the text attributes for this template and fill them in
        var tileAttributes = tileXml.getElementsByTagName("text");

        var title = "Tile Updated At";
        tileAttributes[0].appendChild(tileXml.createTextNode(title));
        tileAttributes[1].appendChild(tileXml.createTextNode(content));

        // create the notification from the XML
        var tileNotification = new notifications.TileNotification(tileXml);

        // send the notification to the app's default tile
        notifications.TileUpdateManager.createTileUpdaterForApplication().update(tileNotification);
    }

})();

Finally, you need to configure the manifest. Double-click package.manifest to bring up the wizard.

  1. In the Application UI tab, change Lock screen notifications to Badge and Tile Text
  2. Supply pointers to a wide tile image and badge image of the required sizes.
  3. In the Declarations tab, add a Background Task
  4. Select Timer
  5. Add backgroundtask.js in the field for Start Page

Run the program.  Click the button and the first time, you will be prompted to enable lock screen access.  Allow it.

Watch the Start Screen.  Find your tile and change it to wide format.  Wait.  The tile should update in 15-30 minutes then every 15 minutes thereafter even if the program is terminated.

 

 

Next Page »

Blog at WordPress.com.
Entries and comments feeds.