Colin Eberhardt's Technology Adventures

Developing Windows Phone 7 HTML5 apps with PhoneGap

September 29th, 2011

This article show the step-by-step development of a Windows Phone 7 HTML5 application using PhoneGap. It also looks at how viable this approach is for cross-platform mobile development.


Colin Eberhardt is a Scott Logic technical Evangelist and a Technical Architect for Visiblox, suppliers of high-performance WPF and Silverlight charts.

Introduction … and Why HTML5?

Windows Phone 7 allows native application development in both Silverlight and XNA, both of which are mature framework with excellent tool support. So why would you want to develop an application with HTML5 / JavaScript instead? Personally I think the only viable reason for doing this (other than just for fun!) is to develop a cross-platform mobile application. HTML5 / JavaScript applications are platform agnostics, running on Android, iPhone, BlackBerry and now with the Mango WP7 supporting IE9, WP7.
In this blog post I will describe how I implemented the application shown below, which allows you to search properties for sale, using the GPS and various webservices to find and geocode your current location:

The basic concept behind HTML5 applications is that your native application is simply a full-screen WebBrowser, which hosts your JavaScript application logic. In order to achieve this in practice, you need to package the HTML, JavaScript, CSS and other resources into a XAP file, then use the WebBrowser APIs to pass messages between your JavaScript code and the native APIs in order to access the phone features such as the camera, accelerometer etc …

A few people have developed frameworks to assist in development of HTML5 apps, for example the HTML App Host Framework. However, the one I would recommend is PhoneGap, as the name implies, this framework fills the gap between your JavaScript code and the native phone features. PhoneGap is an open source project that has been running for a couple of years now; currently a large range of phones are supported, meaning that you are guaranteed the same JavaScript APIs for accessing the phone features on Android, iPhone, BlackBerry and more.

PhoneGap support for Windows Phone 7 was initiated by Matt Lacey, who created an initial implementation of the PhoneGap APIs. More recently Nitobi (who run PhoneGap), announced an official beta release, which they have worked on in conjunction with Microsoft.

Getting Started With PhoneGap

PhoneGap has a project template which will help you create an initial “Hello World” style application. You can get started by following these steps:

  1.  Download the WP7 PhoneGap from https://github.com/phonegap/phonegap-wp7
  2.  Copy the file GapAppStarter.zip, which contains the project template, to the folder
    •  \My Documents\Visual Studio 2010\Templates\ProjectTemplates\
  3.  Create a new project using the GappAppStart project template. I could not locate this template within the tree of ‘Installed Templates’, so used the search function. See the image below.
  4.  Add the framework\WP7GapClassLib.csproj project to your solution and add a reference to this project.
  5. Build and run!

If you followed these steps correctly, you should see the following:

Dissecting the Example App

The example application is a bit more complex than an equivalent Silverlight ‘Hello World’ app, so we’ll look at it in some detail …

The www folder contains the HTML5 application sourcecode, here you place images, HTML, JavaScript, and CSS. These files are marked as ‘content’ and will be included within the XAP file with the same directory structure. The project contains a GapSourceDictionary.xml file, this XML file lists all the HTML application resources. When the application starts, this XML file is read, and each file is added to isolated storage so that it can be served by the WebBrowser control:

<GapSourceDictionary>
  <FilePath Value="www/index.html" /> 
  <FilePath Value="www/phonegap.1.0.js" /> 
  <FilePath Value="www/master.css" /> 
</GapSourceDictionary>

The MainPage.xaml, which is the Silverlight UI for the application contains an instance of PGView:

<phone:PhoneApplicationPage 
    ... xmlns:my="clr-namespace:WP7GapClassLib;assembly=WP7GapClassLib">
    <Grid>
      <my:PGView/>
    </Grid>
</phone:PhoneApplicationPage>

PGView is defined in the WP7GapClassLib, it is a UserControl which hosts a WebBrowser, and contains the code that bridges between the PhoneGap JavaScript APIs and the WP7 .NET APIs. On startup it will load your files into isolated storage and navigate the browser control to “www/index.html” (although this will probably be configurable in future).

The index.html file from the template project is shown below (minus a few un-important parts):

<!doctype html>
<html>
  <head>
    <meta name="viewport" content="width=320; user-scalable=no" />    
      <script type="text/javascript" charset="utf-8" src="phonegap.1.0.js"></script>       
      <script type="text/javascript">
        function init()
        {
          document.addEventListener("deviceready",onDeviceReady,false);
        }
 
        // once the device ready event fires, you can safely do your thing! -jm
        function onDeviceReady()
        {
          document.getElementById("welcomeMsg").innerHTML += "PhoneGap is ready!";
        }
      </script>
 </head>
 <body onLoad="init();">
  <h1>Hello PhoneGap</h1>
  <div id="welcomeMsg"></div>
 </body>
</html>

The important parts to note here are, firstly the viewport metadata, which relates to the complications that small mobile screens present to layout, resulting in the need for a separate layout viewport and visual viewport, as described in the article “a tale of two viewports“. Here the width is set to 320px, so each pixel-width in our HTML is two pixels on screen. I prefer one-to-one correlation, so would change this to the physical phone dimensions. The “user-scalable=no” should prevent the user from being able to pinch-zoom the page, unfortunately on my (mango) phone, this doesn’t seem to be working. This is a shame, because it really spoils the illusion of this being an application rather than a web-page.

When the DOM is loaded, the init function is invoked, which adds a handler for the deviceready event. When this has been fired, it is safe to use the PhoneGap APIs. This example does not actually use any of the APIs, but you can make a simple change to get the phone name via device.name for example to verify that PhoneGap really is working.
So how does the JavaScript / Silverlight bridge work? The PhoneGap.js file communicates via window.external.Notify, which raises the ScriptNotify event within the WebBrowser control. Encoded strings are sent to the PGView control which uses the command pattern to identify the class which performs the required function, and executes it.

Creating the Property Search Application

Following the principles of Unobtrusive JavaScript, where presentation is separated from logic, the I have moved application logic into a file propertySearch.js (adding this to GapSourceDictionary.xml of course). The HTML has the following markup, a simple form that can be used to input the string to search for:

<h1 id="welcomeMsg">Find A Home</h1>
<form id="form" action="#">
  <input type="text" id="searchText"/>
  <input type="submit" id="searchButton" value="Go" />
  <input type="button" id="getLocationButton" value="My Location"/>
</form>

The event handlers are wired up as follows:

$(document).ready(function () {
  document.addEventListener("deviceready", onDeviceReady, false);
});
 
// phonegap is initialised
function onDeviceReady() {
  // verify that the phone is ready!
  $("#welcomeMsg").append("...");
 
  $("#form").submit(searchProperties);
  $("#getLocationButton").click(getGeolocation);
}

Note, I have also added jQuery to the project. The code which appends an ellipsis (…) to the title is a subtle indication that the deviceready event has fired. I found when using the emulator that often the JavaScript code within the page was not being executed at all, this seems to have nothing to do with the PhoneGap JavaScript code. Fortunately the code is always executed when deployed to a real device.

The search properties function is a simple AJAX call to the Nestoria APIs, using the jQuery ajax() function, which manages the JSONP process of dynamically adding a script tag to the DOM which fetches the required data.

var propertyTemplate = $("#propertyTemplate").template();
 
// searches for properties based on the current search text
function searchProperties() {      
  var query = "http://api.nestoria.co.uk/api?" +
                  "country=uk&pretty=1&action=search_listings&encoding=json&listing_type=buy" +
                  "&place_name=" + $("#searchText").val();
  $.ajax({
    dataType: "jsonp",
    url: query,
    success: function (result) {
 
      var resultsContainer = $("#resultsContainer");
      resultsContainer.empty();
      $.each(result.response.listings, function (index, property) {
        var $itemNode = $.tmpl(propertyTemplate, property).data("propertyData", property);
        $itemNode.appendTo(resultsContainer);
      });
    }
  });
 
  return false;
}

NOTE: The application uses the Nestoria UK APIs, so if you are trying it out in your emulator, set your location to somewhere in the UK!

I am using a jQuery templates to render each item. You can render an array of items via the tmpl() function, however, here I render each one individually, so that I can associate the raw JSON data for each property with the generated element via the jQuery data() function. This is rather like defining the DataContext for a Silverlight FrameworkElement.

<script id="propertyTemplate" type="text/x-jquery-tmpl">
  <li class="property" onClick="propertyClick(this); return false;">
    <div class="propertyContainer">
      <div class="thumbnailColumn">
        <img src="${thumb_url}" class="thumbnail"/>
      </div>
      <div class="detailsColumn">
        <div class="title">${title}</div>
        <div class="price">${price_formatted}</div>
      </div>
    </div>
  </li>
</script>

When a property is clicked, the following function is invoked, which locates the clicked DOM element, then extract the JSON property details via the data() function described above. This is used in conjunction with another template to render the property details:

// handle clicks on properties
function propertyClick(propertyNode) {
 
  // get the property
  var property = $(propertyNode).data("propertyData");
 
  // render the template
  $("#detailsContainer").empty();
  $.tmpl(propertyDetailsTemplate, property).appendTo("#detailsContainer");
 
  // switch pages
  showDetailsPage();
}

The template is shown here:

<script id="propertyDetailsTemplate" type="text/x-jquery-tmpl">
  <div>
    <h1>${price_formatted}</h1>
    <img src="${img_url}" class="propertyImage"/>			  
    <h2>${title}</h2>
    <div class="bedrooms">bedrooms: ${bedroom_number}</div>
    <div class="bathrooms">bathrooms: ${bathroom_number}</div>
    <div class="summary">${summary}</div>
  </div>
</script>

The navigation between pages is achieved by having the markup for both pages present in the DOM:

<body>
  <div class="page searchPage">
     ...
  </div>
  <div class="page detailsPage">
    ...
  </div>
</body>

The pages are styled to use absolute positioning:

div.page 
{
  position: absolute;
  width: 480px;  
}

We can then show / hide these pages by simply animating their CSS left property:

function showSearchPage() {
  $(".detailsPage").animate({ left: 480 }, 300, function () {
    $(this).hide();
  });
  $(".searchPage").show().animate({ left: 0 }, 300);
};
 
function showDetailsPage() {
  $(".detailsPage").show().animate({ left: 0 }, 300);
  $(".searchPage").animate({ left: -480 }, 300, function () {
    $(this).hide();
  });
};

It is worth noting that if the IE9 browser supported CSS3 transitions all of the above could have been done declaratively within CSS, unfortunately animations are not in the list of supported features. There is nothing wrong with jQuery animations, they have a very concise and simple syntax. However, CSS3 animation give the browser the option to use GPU acceleration, greatly improving performance. The webkit browsers on Android and iOS support this feature (using the –webkit prefix on the required CSS properties).

The current location is identified via navigator.geolocation.getCurrentPosition, using the Bing Maps REST APIs to geocode from a lat / long coordinate to a postcode:

// gets the current phone location
function getGeolocation() {
  navigator.geolocation.getCurrentPosition(function (position) {
    // geocode via Bing Maps
    var apiKey = "Ai9-KNy6Al-r_ueyLuLXFYB_GlPl-c-_iYtu16byW86qBx9uGbsdJpwvrP4ZUdgD";
    var query = "http://dev.virtualearth.net/REST/v1/Locations/" + position.coords.latitude +
                    "," + position.coords.longitude + "?jsonp=onGeocode&key=" + apiKey
 
    $.ajax({
      dataType: "jsonp",
      url: query
    });
  });
}
 
// handle the geocode results
function onGeocode(result) {
  // extract the 'outward' part of the postcode
  var postalCode = result.resourceSets[0].resources[0].address.postalCode;
  var codeSplit = postalCode.split(" ");
  if (codeSplit.length > 0) {
    $("#searchText").val(codeSplit[0]);
  }
}

Metro-style

The standard style for HTML controls doesn’t look that great, however, with a simple bit of CSS it is possible to re-create something similar to the WP7 Metro styles. Here I have copied some of the properties that are present in the Silverlight resource dictionaries:

body, input, div
{
  font-size: 22.667px; /* PhoneFontSizeMedium */
}
 
h2
{
  font-weight: normal;
  font-size: 32px; /* PhoneFontSizeLarge */
}
 
h1
{
  font-weight: normal;
  font-size: 42.667px; /* PhoneFontSizeExtraLarge */
}
 
input[type="button"], input[type="submit"]
{
  background: black;
  color: white;
  border-color: white;
  border-style: solid;
  padding: 4px 10px;
  border-width: 3px; /* PhoneBorderThickness */
  font-size: 25.333px; /* PhoneFontSizeMediumLarge */
}
 
input[type="button"]:active, input[type="submit"]:active
{
  background: white;
  color: black;
}
 
input[type="text"]
{
  width: 150px;
  padding: 4px;
}

ProgressBar

For a bit of fun I thought I’d try and create a HTML equivalent of the ‘trailing dots’ WP7 ProgressBar. With a simple bit of markup / CSS:

<div class="progress">
  <div class="pip"></div>
  <div class="pip"></div>
  <div class="pip"></div>
  <div class="pip"></div>
  <div class="pip"></div>
</div>
.progress div
{
  width: 5px;
  height: 5px;
  overflow: hidden;
  position: absolute;  
  background: green;
}
 
.progress
{
  position: relative;
  height:10px;
}

And some further jQuery animations, this time making use of the easing plugin:

function onDeviceReady() {
  ...
 
  // create an animation loop for the progress bar;
  startAnimation();
  var tid = setInterval(startAnimation, 3500);
}
 
function startAnimation() {
  var delay = 200;
  $(".pip").each(function () {
    animatePip($(this), delay);
    delay += 200;
  });
}
 
function animatePip(element, delay) {
  element.css("left", 0)
        .hide()
        .delay(delay)
        .show()
        .animate({ left: 240 }, { duration: 1000, easing: "easeOutSine" })
        .animate({ left: 480 }, { duration: 1000, easing: "easeInSine" });
}

We get something which approximates the WP7 progress bar:

(Note, sometimes the animation goes a bit crazy, try refreshing your browser to reset it!)

Again, my comments regarding CSS3 animations and GPU acceleration apply here also.

Tombstoning

As I have discussed in a previous blog post, tombstoning is a tricky task for WP7 developers. When your application is tombstoned you can save application state, page state – and the framework stores your back-stack URIs. It is your responsibility to re-start your application in the same state. Contrary to the belief of some developers I have talked to, Mango does not remove the need to tombstone, it just means that your application is likely to be tombstoned less often, with the suspended state being used to park your application while application switching.

So, how does tombstoning work with a PhoneGap HTML5 application? Good question! Implanting tombstoning would probably require some custom communication, outside of the PhoneGap APIs, that allows the JavaScript application to provide its current state to the Silverlight application that hosts this.

I would be very interested to hear from anyone who has solved this issue!

The Development Process

Attempting to develop JavaScript applications with the browser within the WP7 emulator is not a pleasant process. Any JavaScript errors, including simple parsing errors, typically result in the HTML being rendered but the scripts ignored. A much better approach is to run your HTML / JavaScript within a browser, this gives you access to the usual developer tools such as Firebug, or the built in Chrome / IE tools.

However, to do this, you need to mock the PhoneGap APIs. For my application, I found the following did the trick:

document.addEventListener = function (evt, handler, capture) {
  $("body").bind(evt, handler);
};
 
$(document).ready(function () {
  setTimeout(function () {
    $("body").trigger("deviceready");
  }, 100);
});

OK, I know what you are thinking, what about the geolocation code? Where is the mock for these PhoneGap APIs? The answer is that a number of the PhoneGap APIs are designed to exactly match the corresponding HTML5 specification. So for example, the PhoneGap geolocation API is exactly the same as the HTML5 geolocation APIs. For phones such as WP7 where the browser supports this HTML5 feature, PhoneGap does nothing, for phones that do not, PhoneGap provides an implementation (using the native APIs).

If the PhoneGap mock is so simple, you might be wondering, why use PhoneGap at all? Well, PhoenGap is still giving us a mechanism for packaging files into a XAP file in such a way that they can be rendered by the browser.

How cross-platform is this approach?

I would say that this approach is probably about as cross-platform as any HTML5 / JavaScript browser based application. There are always going to be cross-browser differences to overcome. As a test, I ran this code on an iPod Touch without any modification. The results are pretty good, although there are some quirks visible:

How viable are HTML5 applications?

It is clear that there is a growing trend towards cross-platform HTML5 applications, and Microsoft seem to be in support of this concept (even though the JavaScript / HTML5 Metro applications within Win8 are not cross-platform!). Microsoft has worked with Nitobi to create the PhoneGap for WP7, it was also announced at the //build/ conference that Microsoft would be working with jQuery Mobile to create a Metro theme for their mobile controls.

Currently, PhoneGap for WP7 is in beta, and it is certainly a little rough around the edges. This will no doubt improve in time. The large list of applications written with PhoneGap, certainly indicate that this is a viable solution for application development.

A larger obstacle for WP7 HTML5 applications is the IE9 browser that runs in the Mango phone. Whilst it has a pretty impressive list of HTML5 features supported, there are a couple of browser features / issues that I cannot resolve. These make it obvious to any user that this is in fact a browser application, totally spoiling the ‘illusion’

  1. user-scalable=no – currently this setting seems to be ignored. This means that the user can pinch your application, which makes it feel like a web page. UPDATE Roy, in a comment below pointed out that the viewport parameters should be comma-separated. This almost solves the issue. The user can still pinch the view, which causes it to zoom, but when the pinch finishes, the viewport returns to the original scale. Not perfect, but better than nothing!
  2. There doesn’t seem to be any way to turn of the gray shaded rectangle that appears over links when you click them. With applications that have dynamic content, this can look pretty ridiculous, with a gray rectangle lingering on screen while the page content changes underneath it. With the Android / iPhone browsers this can be turned off in CSS via -webkit-tap-highlight-color

Hopefully these limitations will be resolved. When they do, I am quite sure that HTML5 will be a viable technology for creating quality phone applications.

You can download the project sourcecode here: PhoneGapExample.zip

Regards, Colin E.

Building Windows Phone Apps – a free WP7 eBook

September 22nd, 2011

I’ve just had an email land in my inbox from Microsoft’s Mike Ormond, announcing that the Windows Phone 7 book that I contributed a couple of chapters to (Introduction and Tools), has finally been published!

This is a collaborative book with contributions from Pete Vickers, Andy Gore, Mike Hole, Gergely Orosz, Sasha Kotlyar, Dominic Betts, Will Johnson, Ben Cameron, James Bearne, Samidip Basu, Paul Marsh, Stuart Lodge, Colin Eberhardt – and of course Mike Ormond and the other rest of the staff at Microsoft UK.

So, why not download the book and find out more about Windows Phone 7 development?

Regards, Colin E.

Windows 8 – An OS of two halves.

September 15th, 2011

In this blog post I take a look at Windows 8 on the outside, from a user perspective; and on the inside, from a developer perspective to see how it will change the way we develop with Windows on tablets, smartphones and the desktop when it is released next year.

In Anaheim, California, the Microsoft //build/ conference is drawing to a close. And as the attendees head for home, with their shiny new Samsung tablets under their arms, the news of Windows 8 and the impact it has on end-users and developers is starting to sink in around the globe.

There is no doubt that the impact of Windows 8 is going to be very large, it heralds the biggest change in the Windows architecture since 1993 and from an end-user perspective it is like no other version of Windows before it.

So why such a radical change to both the UI and the architecture? and why now? The answer to this question is quite simple … tablets. Previous versions of Windows have been targeted primarily at the desktop, laptop and netbook form-factors where the primary input devices are mouse and keyboard, and memory, disk-space, CPU performance is aplenty. Tablets have made the odd cameo appearance in the history of computing, but it is only recently with the launch of the iPad that they have suddenly become mainstream.

To take the Windows OS to a tablet it needs to be stripped-down, made faster and support multi-touch (or touch-first – a new Microsoft buzzword) and with Windows 8 Microsoft have done just that. With the requirements of a tablet interface being so different to a desktop, how have Microsoft reconciled these differences? The answer is a little surprising … they haven’t! They could have launched a dedicated Tablet Windows OS, just as they have done on the mobile with Windows Phone 7, but instead they have launched a single OS that works for both tablet and desktop. As a result it has something of a split personality. You can choose to run either the Metro or the ‘classic’ desktop UI on your tablet computer and you have exactly the same choice on your desktop.

An end-user perspective

The Windows 8 user interface uses the same Metro style that Microsoft introduced with Windows Phone 7, bright colours, clean edges, a lack of drop-shadows and other adornments. The style is heavily influenced by fonts and designs used for road and street-signs. The same concepts of clarity-at-a-distance translates very well to a small smartphone screen and should be equally at home on the tablet.

When applications are launched they run full-screen, with a similar multi-tasking model to Windows Phone 7 where hidden applications are suspended. These features, combined with the fast shutdown / restart times make sense for tablet users where limiting the work that the processor does will significantly enhance battery life.

You can run multiple applications side-by-side in a split-screen mode:

The current preview of Windows 8 has a few of the familiar applications available in the new Metro-desktop, these include IE which is now chromeless, i.e. it is permanently in full-screen mode. Gestures are used to reveal the open tabs or URL. Notably the Metro IE does not support any plugins, i.e. Flash, Silverlight – more on this later!

Metro applications for Windows 8 are distributed via the Windows Marketplace in much the same way as they are for Windows Phone (and iPad, Android etc…).

The Windows 8 UI clearly has tablets in mind and recent reviews by Engadget and Gizmodo seem to indicate that the experience is very good and agree that when released it could be a serious competitor to the iPad.

However, hidden behind the glossy Windows 8 UI sits the more traditional Windows 7 style desktop. Simply click (or touch) the desktop button and the old-familiar Windows desktop appears. It almost feels like the desktop is an app running within the new Metro UI – you can also run a split screen which combines the Metro and desktop UIs:

Interestingly if you want to run IE with plugins, there is a fully-featured version of IE present on the desktop. Try explaining these differences to your grandmother!

For a tablet, Windows 8 gives you the best of both worlds, an immersive and tactile Metro interface, plus the old-familiar Windows desktop.

On the desktop, Windows 8 does feel a bit strange. Metro applications are designed to work with the mouse and the keyboard, so it functions just fine, however, on a desktop monitor the Metro UI feels like a bit large and a touch gimmicky. The Metro concepts work well for small screens, but in my opinion are less effective on a large desktop monitor, especially in the absence of touch. I doubt it will make a big impact for desktop users, but at least they have the choice! When used on a PC with multiple monitors the new Metro UI is confined to a single screen, again further illustrating its tablet focus.

A developer perspective

Windows 8 marks a radical change from the outside, but what about on the inside? What is the developer story?

One of the most important diagrams revealed in the keynote is the Windows 8 architecture diagram:

It is clear that the split personality of Windows 8 runs very deep. In this diagram you can see that Metro style apps and desktop apps share the kernel, but nothing else. This is a pretty significant change in Windows architecture; Metro apps are finally free of the Win32 APIs which .NET has been built upon.

The APIs for developing Metro apps reside within the WinRT. A few keys things to know about this new architecture are:

  • WinRT applications are chromless, fullscreen, with no pop-up or modal dialogs
  • WinRT is an Object Oriented replacement for Win32
  • WinRT is very similar to .NET, however a number of APIs such as file I/O, security etc… are not present.
  • You can develop with C++, or C# etc… in much the same way as .NET applications
  • The UI defined using XAML, as per WPF and Silverlight
  • You can potentially port Silverlight applications to WinRT by changing a few namespaces
  • JavaScript is a first-class citizen of Windows 8, using a HTML UI

The above already tells us a lot about WinRT and Metro applications. My first thoughts are that they are much more similar to Windows Phone 7 applications than desktop WPF applications. They live within a sandbox which uses a restricted subset of APIs, you certainly cannot write a virus checked or hard disk partitioning tool with WinRT!

Furthermore, when developing Metro UI apps, Visual Studio ‘deploys’ your application too your Windows 8 Metro desktop in exactly the same way as it does with the WP7 phone.

So what about existing .NET applications? The important thing to know is that all the ‘old’ APIs are still there. Your WPF, Silverlight and WinForms applications are safe! There were also a few new WPF features announced at //build/ as part of .NET4.5, but they are not very interesting, it is clear that Microsoft has been putting its energy into other things.

The JavaScript / HTML5 story is a bit of an odd one. Clearly Microsoft has embraced these technologies, with JavaScript having full access to the WinRT. Furthermore, they have added APIs for creating Metro UIs with HTML. However, I am not sure why someone would want to use JavaScript to create Windows 8 Metro applications? The main strength of JavaScript and HTML5 is the portability due to its support on a wide range of browsers, tablets, phones, etc… The Windows 8 JavaScript Metro apps are ‘tied’ to WinRT so are in no way portable.

Questions …

Lots of questions … the rather complicated nature of Windows 8 has resulted in quite a lot of confusion.

Is Silverlight Dead? – this was probably the most oft asked question before //build/ and it is still being asked. The news that the Metro IE10 will not run Silverlight is certainly not good news for the technology, however, it does not mean it is dead – Silverlight is still present in the desktop IE10 browser (as is Flash). Recently Silverlight has been re-positioned as the technology of choice for more complex line-of-business applications, the types of application which sit better in the Windows 8 ‘classic’ desktop. Furthermore, whilst the Metro UI is leading the push into tablet computing, I doubt it will take off on the desktop. So, no, Silverlight is not dead, but it has unfortunately missed out on being part of the Metro UI for tablets.

There is a relatively simple migration path for Silverlight and Windows Phone 7 applications to the new Metro WinRT. This might work for full-screen Silverlight applications, but will not work for applications that mix HTML and Silverlight content within a browser.

Is WPF Dead? – Again, for much the same reasons as Silerlight the answer is “no”. WPF is a framework intended for line-of-business applications, and those belong on the Windows 8 desktop.

How does this impact Windows Phone 7? – it doesn’t. The next version of WP7 is going RTM shortly and there has been no change to these plans. In fact for WP7 developers Windows 8 is a great opportunity. The WinRT seems most closely related to Silverlight for WP7, so your skills and code are readily portable to the tablet.

Should I write my app as a desktop or Metro app? – this is probably the single hardest question that the Windows 8 preview has raised. As application developers we now have two very different ways which we can deliver applications to the desktop and tablet, either the new Metro UI, powered by the (deliberately) limited WinRT; or desktop applications using WPF or Silverlight. I think it will be very interesting to see how Microsoft tackles this problem with its own applications. So far the Windows 8 preview has Metro UI based Twitter, Weather and Social Networking applications and a desktop based Visual Studio. There is also IE which is available in both desktop and Metro, albeit with quite different functionality. Where will Outlook, Word, Excel sit in the new Windows 8?

I think there are rather a lot of applications that will want to make use of both Metro and desktop UIs. Take Outlook for example, you could imagine a simplified Metro interface sitting on one of your monitors, but a more feature rich desktop version available on the other.

One other point worth considering is ‘reach’. It will take a long time before everyone is running a Windows 8 PC, so if you choose to deliver your application as a Metro app, you are restricting yourself just to the Windows 8 user-base. However, if you are targeting the Windows tablet, you can of course guarantee that they will run Windows 8.

Conclusions

Windows 8 presents a significant change in the way we develop Windows applications. The split personality of the Windows 8 user interface and architecture is going to cause confusion on many levels.

The technical implications of WinRT and how it relates to .NET are slowly starting to become clear, thanks to great blog posts like “WinRT Demystified”.

Personally what I think will take a little bit longer to understand is how we design applications for Windows 8, as we start to discover what works well in Metro, what should remain on the desktop and what we deliver to both.

Regards, Colin E.

Implementing a Windows Phone 7 Conversation View Part Two

August 8th, 2011

This blog post describes how to implement a conversation / messaging style application with Windows Phone 7. It covers how to style the speech bubbles and the scrolling of the conversation list view when the phone keyboard is shown.

A couple of weeks ago I wrote a blog post which described the creation of a Windows Phone 7 ConversationView, a view which renders a list of messages so that they look like a conversation. In this blog post I am going to extend the concept further, by adding an input text field allowing you to have a conversation with ELIZA, an A.I. chatterbot. This blog post will look at some of the tricky issue regarding scrolling the list of messages so that the most recent is always visible when responding.

You can see a video of this code in action below:

I hoped that I could find a decent C# ELIZA (a classic chatter application that takes on the role of a therapist) implementation on the internet, however, the only one I found was rather basic. If you know of any alternatives, pleas let me know!

In my previous blog post I created a UserControl which renders each Message instance, where the template used to render the message is dependant on which side of the conversation it relates to. Refer to my previous blog post for implementation details.

The layout for my simple chat application uses an instance of the ConversationView user control, with a text input located at the bottom of the screen:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  <Grid contribControls:GridUtils.RowDefinitions=",Auto">
 
    <ScrollViewer x:Name="ConversationScrollViewer">
        <!-- conversation view -->
        <local:ConversationView x:Name="conversationView"/>
      </StackPanel>
    </ScrollViewer>
 
    <!-- the text input field -->
    <Grid Grid.Row="1"
          contribControls:GridUtils.RowDefinitions=",,"
          Margin="0,10,0,0">
      <Rectangle Fill="White"
                  Grid.RowSpan="2"/>
      <txt:WatermarkedTextBox Watermark="type a message"
                              TextWrapping="Wrap"
                              AcceptsReturn="True"
                              Padding="0"
                              x:Name="TextInput"
                              GotFocus="TextInput_GotFocus"
                              LostFocus="TextInput_LostFocus"/>            
      <Path Data="m 0,0 l 16,0 l 0,16 l -16,-16"
            Fill="White"
            Margin="0,0,5,0"
            HorizontalAlignment="Right"
            Grid.Row="2"/>
    </Grid>
  </Grid>      
</Grid>

Note the simplified Grid markup from the WP7Contrib codeplex project, where the string ",Auto" is used in place of the more verbose RowDefinition XAML elements.

The WatermarkedTextBox is from an article by WindowsPhoneGeek (and it works like a charm – thanks!). A simple Path and Rectangle are added to the layout so that the input field looks like a speech bubble.

When the user clicks on the input TextBlock the phone keyboard will be revealed, allowing them to enter their message. This is where we stumble upon our first major problem!

When the phone keyboard is displayed, your application content is ‘pushed’ upwards to make space for the keyboard. Unfortunately, this results in the message which the user is replying to being pushed off the top of the screen …

Because our ConversationView sits within a ScrollViewer we can scroll to push the message further down the screen, however, this would require a negative scroll offset, which isn’t possible!

To circumnavigate this issue, we can add an element which is used to ‘push’ the top message downwards so that it is located at the bottom of the ScrollViewer. The following markup adds a Rectangle which sits above the ConversationView, with two Storyboards that expand / collapse the Rectangle allowing us to push the messages down when we need them:

<ScrollViewer x:Name="ConversationScrollViewer">
  <StackPanel Orientation="Vertical"
              x:Name="ConversationContentContainer"
              VerticalAlignment="Top">
    <!-- padding element -->
    <Rectangle Width="100"
                Height="0"
                x:Name="PaddingRectangle">
      <Rectangle.Resources>
        <Storyboard x:Name="PaddingRectangleShowAnim">
          <DoubleAnimation Storyboard.TargetName="PaddingRectangle" 
                Storyboard.TargetProperty="(Height)"
                To="400"  Duration="00:00:00.3"/>
        </Storyboard>
        <Storyboard x:Name="PaddingRectangleHideAnim">
          <DoubleAnimation Storyboard.TargetName="PaddingRectangle" 
                Storyboard.TargetProperty="(Height)"
                To="0"  Duration="00:00:00.3"/>
        </Storyboard>
      </Rectangle.Resources>
    </Rectangle>
 
    <!-- conversation view -->
    <local:ConversationView x:Name="conversationView"/>
  </StackPanel>
</ScrollViewer>

We can detect when the input TextBlock receives focus to determine when the keyboard will be revealed. Using the Show / Hide extension methods I blogged about a while back, we can fire the animations which make this padding rectangle grow or shrink when the keyboard is shown or hidden:

private void TextInput_GotFocus(object sender, RoutedEventArgs e)
{
  PaddingRectangle.Show();
  ApplicationBar.IsVisible = true;
}
 
private void TextInput_LostFocus(object sender, RoutedEventArgs e)
{
  PaddingRectangle.Hide();
  ApplicationBar.IsVisible = false;
}

If we fill the rectangle so that it is visible, you can see how it pushes down the content as shown below:

The next step is to ensure that the ConversationView is always scrolled so that the most recent message is visible. The ScrollViewer has a ScrollToVerticalOffset method which can be used to programmatically scroll the content, however, because this is not a dependency property it cannot be animated via Storyboard.

Here I am using the same trick I employed for the Windows Phone 7 Jump List control, where a private dependency property that sets the scroll offset value in its change handler is used as a target for the scrolling Storyboard:

/// <summary>
/// VerticalOffset, a private DP used to animate the scrollviewer
/// </summary>
private DependencyProperty VerticalOffsetProperty = DependencyProperty.Register("VerticalOffset",
  typeof(double), typeof(MainPage), new PropertyMetadata(0.0, OnVerticalOffsetChanged));
 
private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  MainPage app = d as MainPage;
  app.OnVerticalOffsetChanged(e);
}
 
private void OnVerticalOffsetChanged(DependencyPropertyChangedEventArgs e)
{
  ConversationScrollViewer.ScrollToVerticalOffset((double)e.NewValue);
}

Using this dependency property we can create a simple Storyboard and DoubleAnimation that scrolls to reveal the latest message:

private void ScrollConvesationToEnd()
{
  // start from the current position
  scrollViewerScrollToEndAnim.From = ConversationScrollViewer.VerticalOffset;
 
  // set the scroll position to the the height of the contained content
  scrollViewerScrollToEndAnim.To = ConversationContentContainer.ActualHeight;
 
  // go!
  scrollViewerStoryboard.Begin();
}

And there you have it, a fully functional conversation application. Enjoy!

You can download the complete sourcecode: WP7ConversationView.zip

Regards, Colin E.