21 May 2014

Windows Phone emulator–“Unable to create a route between the waypoints”

The Windows Phone 8.1 emulator has a beautiful new option: if you want to simulate a route you don’t have to put in a gazillion points anymore, you just input two (or some more if you want specific waypoint), the emulator automatically calculates a route and off you go, in this case from my home to some location near Amsterdam:

image

Only for some people it does not work out so well. I have seen some reports of people getting this popup, whatever two points they entered, even if those two were very close together with an obvious route:

image 

Today my friend Matteo Pagani ran into the same problem – and using a remote access tool I was able to have a look at his computer and determine once and for all the root cause of this. And it’s very simple – Matteo had set his computer to English like me, but still had the European decimal number setting. For those who are not familiar with that – when an European wants to write “a hundred thousand and a half” he writes “100.000,5” where an American typically writes “100,000.5”. Decimal point and comma are reversed. Whoever thought up this reversal, well let’s stay civilized here but I don’t have very warm feelings toward him or her, let’s put it that way. For some reason, in Geographical Information Systems territory, this is a fairly common problem. I have set my computer to the American number style for longer than I care to remember so I never ran into it.

To fix this, you have to adopt the American style of numbers in Windows. Go to your Control Panel, search for number and select “Change date, time or number formats”

image

Then in the next dialog

image

“Decimal symbol” should be set to . (dot) and “Digit grouping symbol” to , (comma). For extra fun, the difference is hard to spot. Close Visual Studio and the emulator, restart Visual Studio, bring up the emulator again, and presto.

I know – this affects all programs in Windows so now your Excel sheets will show up in American style. Don’t shoot the messenger, I am just reporting the problem and a work-around. It’s not the end of the world. I don’t think much people will spend days and days simulating routes ;-)

06 May 2014

Writing behaviors in PCL for Windows Phone 8.1 and Windows 8.1

This article was updated after a tip from Daniel Plaisted – see comments

I was happily adding Windows Phone 8.1 support to WpWinNl – or actually support for Universal Windows Apps - when I noticed that basically all I was doing was linking files from the Windows 8.1 project – without any changes. Convergence FTW! Although that made adding the support as such pretty simple, I also envisioned a maintenance nightmare coming towards me as would not only need to maintain links between Windows 8.1 and Windows Phone 8.0, but also between Windows 8.1 and Windows Phone 8.1. Maybe it was time to go PCL. That went pretty well, until I hit a major roadblock.

This roadblock, my friends, is very simple: the behaviors SDK, and thus everything in Microsoft.Xaml.Interactivity, is not available to PCL. This has probably to do with the fact that the behaviors SDK for Windows 8 is a separate entity, not part of the core framework, that was added later. This same characteristic has moved over to Windows Phone 8.1. It basically boils down to this: every behavior must implement Microsoft.Xaml.Interactivity.IBehavior and this is sitting in two separate assemblies – one for Windows, one for Windows Phone. On my Surface Pro they are sitting in C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1\ExtensionSDKs\BehaviorsXamlSDKManaged\12.0\ for Windows 8.1 and in C:\Program Files (x86)\Microsoft SDKs\WindowsPhoneApp\v8.1\ExtensionSDKs\BehaviorsXamlSDKManaged\12.0\ for Windows Phone 8.1

Now what?

Of course, like I wrote before, you can moan and complain about this and send venomous tweets to Joe Belfiore, Cliff Simpkins or just the first Windows Phone MVP you can find – or you can pause and think if there’s a way around it. This is the thing I love to do – explore, thinker, invent – and come to a solution. Because as it turns out, my friends, there is one.

imageThe key to the solution is this pretty odd article that, believe it or not, was sent to a closed mailing list of Windows Phone MVPs to collect opinions on – by none other than Matthijs Hoekstra, just the day before I wrote this. Then I thought it was a crazy idea - today I find it an invaluable clue. Talking about coincidences. It’s like basic research – you never know where the next life saving idea will be coming from ;-) .

It’s called the “Bait and switch PCL trick” and it basically makes use of a very odd NuGet trick – it will always prefer a native platform library over a PCL. If you make a NuGet package that contains both a PCL and a native version, the PCL is then only used at compile time. So what I did was create this crazy NuGet package called CrossPlatformBehaviorBase (I think I am going to change that later) that basically has three projects in it: once PCL, one Windows Phone 8.1, and one Windows 8.1.

The key thing is that the implementation for Windows Phone and Windows are the same (in fact, the Windows Phone 8.1 implementation is linked from the Windows implementation, but the PCL is slightly different. The PCL version is a copy of the normal IBehavior interface, namespace and all:

using Windows.UI.Xaml;

namespace Microsoft.Xaml.Interactivity
{
  public interface IBehavior
  {
    DependencyObject AssociatedObject { get; }

    void Attach(DependencyObject associatedObject);

    void Detach();
  }
}

Whereas the Windows Phone and Windows implementations look like this:

[assembly: System.Runtime.CompilerServices.TypeForwardedTo(
typeof(Microsoft.Xaml.Interactivity.IBehavior))]

Indeed, that is all. A type forwarding statement to convince the compiler to look for the right IBehavior at runtime. I did not know this trick, but Daniel Plaisted alerted me in the comments.

imageIf you build for release this will create three projects neatly conforming to NuGet naming specifications and finally run a little command file that creates a NuGet package in the output folder directly under the solution folder.

To be able to install the package, you need to specify that folder as a NuGet source:

image

imageMind you, in the future this will all be on NuGet so you won’t have to put up with this. For now,  am just explaining how it’s done.

Anyway, I went ahead and created an Universal Windows App DemoApp, and added a Windows Phone 8.1/Windows 8.1 PCL “WpWinNl” to the solution.

The newly created NuGet package needs to be installed in all three projects: 

imageAnd then I started in copying stuff from WpWinNl,starting with the Behavior base class that I created to maintain compatibility with ‘Silverlight style’ behaviors:

using Windows.UI.Xaml;

namespace WpWinNl.Behaviors
{
  public abstract class Behavior : DependencyObject, IBehavior
  {
    public DependencyObject AssociatedObject { get; set; }

    public virtual void Attach(DependencyObject associatedObject)
    {
      AssociatedObject = associatedObject;
    }

    public virtual void Detach()
    {
    }
  }
}

This will compile fine, now I have the replacement IBehavior in the PCL version. We continue with the Behavior<T> which of course compiles as well:

namespace WpWinNl.Behaviors
{
  public abstract class Behavior<T> : Behavior where T: DependencyObject
  {
    [System.ComponentModel.EditorBrowsable(
       System.ComponentModel.EditorBrowsableState.Never)]
    public new T AssociatedObject { get; set; }

    public override void Attach(DependencyObject associatedObject)
    {
      base.Attach(associatedObject);
      this.AssociatedObject = (T)associatedObject;
      OnAttached();
    }

    public override  void Detach()
    {
      base.Detach();
      OnDetaching();
    }

    protected virtual void OnAttached()
    {
    }

    protected virtual void OnDetaching()
    {
    }
  }
}

imageWhich basically comes over from the existing WpWinNl implementation unchanged. For kickers, I then put my infamous DragFlickBehavior, and all my animation code that has been featured on this blog multiple times on top of it and lo and behold – with a minor addition it just works. And I was able to delete all #ifdef statements for Windows Phone out, leaving only the former ‘just windows’ code. All in PCL. And all usable both on Windows Phone and Windows.

image
As coupe de grace I put the whole of MainPage.xaml in the shared portion, opened Blend and sure enough – there was my DragFlickBehavior:

So I dropped a date picker, a text box and a button on the screen and dragged my PCL-DragFlickBehavior on top on all three:

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    
    xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
    xmlns:behaviors="using:WpWinNl.Behaviors"

    x:Class="DemoApp.MainPage"
    mc:Ignorable="d">

  <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button Content="Button" HorizontalAlignment="Left" Height="37" 
      Margin="101,114,0,0" VerticalAlignment="Top" Width="108">
      <Interactivity:Interaction.Behaviors>
        <behaviors:DragFlickBehavior/>
      </Interactivity:Interaction.Behaviors>
    </Button>
    <DatePicker HorizontalAlignment="Left" Margin="48,230,0,0"
VerticalAlignment="Top"> <Interactivity:Interaction.Behaviors> <behaviors:DragFlickBehavior/> </Interactivity:Interaction.Behaviors> </DatePicker> <TextBlock HorizontalAlignment="Left" Height="42" Margin="132,310,0,0" TextWrapping="Wrap" Text="Blabla" VerticalAlignment="Top" Width="121"> <Interactivity:Interaction.Behaviors> <behaviors:DragFlickBehavior/> </Interactivity:Interaction.Behaviors> </TextBlock > </Grid> </Page>

And sure enough:imageimage

 

 

 

 

 

 

 

 

The screen shows up and you can happily drag the items along, although dragging a Windows Phone date picker is quite a challenge.

So there you have it – behaviors completely defined in PCL, courtesy of a little NuGet trick. Could the Windows Phone and/or Windows Team have done this themselves? Possibly – but don’t forget I just sailed past anything that is not managed, like C++. And if there ain’t any challenges for MVPs to meet, fat lot of use we would be, eh? ;-)

A zip file with both the NuGet package and the Universal Windows App can be found here. For now it’s a kind of proof of concept, soon I will be putting this NuGet package out on NuGet itself and use it for the new version of WpWinNl. After some rigorous testing ;).

Update – after some thinking I decided to call this IBehaviorPortable and have uploaded it to NuGet with that name.

MovedCheeseException–where is StorageFolder.TryGetItemAsync in Windows Phone 8.1?

A quickie this time: when I finally started porting WpWinNl over to Windows Phone 8.1 (sorry, I was busy testing, preparing a talk and the Windows Phone Code Battle, so something had to give) and was getting into the nuts and bolts of some of my code I noticed something peculiar. Somewhere in my code the StorageHelper class, that sports this little method.

private async Task<StorageFile> GetDataFile()
{
  var result = 
    await ApplicationData.Current.LocalFolder.TryGetItemAsync(GetDataFileName(typeof(T)));
  return result as StorageFile;
}

got a compiler error on the TryGetItemsAsync method. So although Microsoft works hard on convergence for Windows Phone and Windows, apparently for some reason this method did not make the cut. In a Windows Phone / Windows 8.1 PCL it is not available either.

Now of course you can cry foul and say that once again Microsoft is pulling the rug out from under you, the loyal developer, or something to that effect – or you can just solve the problem. Either you change the line that does not compile to something that does compile on all platforms, for instance

var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
var result = files.FirstOrDefault(p => p.Name == name);

Or if you are a really lazy bastard  - like me – and just want to leave existing code intact, you can just make an extension method that you tuck in a library like this:

using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;

namespace WpWinNl.Utilities
{
  /// <summary>
  /// Replaces the missing TryGetItemAsync method in Windows Phone 8.1
  /// </summary>
  public static class StorageFolderExtensions
  {
    public static async Task<IStorageItem> TryGetItemAsync(this StorageFolder folder, 
                                                           string name)
    {
      var files = await folder.GetItemsAsync().AsTask().ConfigureAwait(false);
      return files.FirstOrDefault(p => p.Name == name);
    }
  }
}

And we’re  done here. Sometimes your cheese moves a little. Deal with it, that’s what it takes to be a developer ;-). As this article basically talks about two lines of code, I will dispense with the sample solution this time if you don’t mind.

Thanks to Dave Smits for pointing out on Twitter that I should add AsTask().ConfigureAwait(false), which I did. As I am writing a library, I should not interfere with the developer's way of handling thread safety. Here is explained why.