24 July 2012

A WinRT behavior to mimic EventToCommand

This is deprecated. Please use the official behaviors SDK now. See here for a simple migration guide

Updated September 2 2012 with two sample applications

Whoever used the MVVMLight framework by Laurent Bugnion is familiar with EventToCommand, especially those who used it on Windows Phone before the advent of 7.5 (or SDK version 7.1.1). This utility enables triggers to fire commands on the viewmodel

Unfortunately, in WinRT there is no such thing as a trigger, so this method cannot be used, and MVVMLight for WinRT therefore does not include EventToCommand. This morning I got a DM from AESIR Consultancy asking me if I had a solution for that, because he had some trouble porting a Windows Phone app to Windows 8. I did not have it then, but I had the feeling it could be done quite easily. In the afternoon, in the time between I came home and my wife came home from work I wrote this behavior that basically does the same as EventToCommand.

And indeed, WinRT does not support behaviors either, but that has been solved already. In order for this to work, you will need to download the NuGet WinRtBehaviors package

Anyway – the behavior. You start out with a project with references to WinRtBehaviors and the Reactive extensions – ReSharper 7 EAP found them readily and automatically attached references to my projects which now has the following references to reactive stuff:

  • System.Reactive.Core
  • System.Reactive.Interfaces
  • System.Reactive.Linq
  • System.Reactive.PlatformServices

So we start out with the class definition and some boring Dependency property definitions:

using System;
using System.Reactive.Linq;
using System.Reflection;
using System.Windows.Input;
using WinRtBehaviors;
using Windows.UI.Xaml;

namespace Win8nl.Behaviors
{
  /// <summary>
  /// A behavior to imitate an EventToCommand trigger
  /// </summary>
  public class EventToCommandBehavior : Behavior<FrameworkElement>
  {

    #region Event

    /// <summary>
    /// Event Property name
    /// </summary>
    public const string EventPropertyName = "Event";

    public string Event
    {
      get { return (string)GetValue(EventProperty); }
      set { SetValue(EventProperty, value); }
    }

    /// <summary>
    /// Event Property definition
    /// </summary>
    public static readonly DependencyProperty 
      EventProperty = DependencyProperty.Register(
        EventPropertyName,
        typeof(string),
        typeof(EventToCommandBehavior),
        new PropertyMetadata(default(string)));

    #endregion

    #region Command

    /// <summary>
    /// Command Property name
    /// </summary>
    public const string CommandPropertyName = "Command";

    public string Command
    {
      get { return (string)GetValue(CommandProperty); }
      set { SetValue(CommandProperty, value); }
    }

    /// <summary>
    /// Command Property definition
    /// </summary>
    public static readonly DependencyProperty 
      CommandProperty = DependencyProperty.Register(
        CommandPropertyName,
        typeof(string),
        typeof(EventToCommandBehavior),
        new PropertyMetadata(default(string)));

    #endregion

    #region CommandParameter

    /// <summary>
    /// CommandParameter Property name
    /// </summary>
    public const string CommandParameterPropertyName = "CommandParameter";

    public object CommandParameter
    {
      get { return (object)GetValue(CommandParameterProperty); }
      set { SetValue(CommandParameterProperty, value); }
    }

    /// <summary>
    /// CommandParameter Property definition
    /// </summary>
    public static readonly DependencyProperty 
        CommandParameterProperty = DependencyProperty.Register(
        CommandParameterPropertyName,
        typeof(object),
        typeof(EventToCommandBehavior),
        new PropertyMetadata(default(object)));

    #endregion
  }
}

All very boring, all very standard. Now, for dynamically adding a listener to the event: I’ve been down this road before, say hello to our friend Observable.FromEventPattern, which takes away all the boring details about the differences between ordinary and WinRT events.

protected override void OnAttached()
{
  var evt = AssociatedObject.GetType().GetRuntimeEvent(Event);
  if (evt != null)
  {
    Observable.FromEventPattern<RoutedEventArgs>(AssociatedObject, Event)
      .Subscribe(se => FireCommand());
  }
  base.OnAttached();
}

Nothing special. Try to find an event with the same name as the contents of the “Event” property and add a listener to it. And the final piece of the puzzle is the actual implementation of FireCommand. Of course, I could have implemented this inline but I like to make this a separate method, if only for readability:

private void FireCommand()
{
  var dataContext = AssociatedObject.DataContext;
  if (dataContext != null)
  {
    var dcType = dataContext.GetType();
    var commandGetter = dcType.GetRuntimeMethod("get_" + Command, new Type[0]);
    if (commandGetter != null)
    {
      var command = commandGetter.Invoke(dataContext, null) as ICommand;
      if (command != null)
      {
        command.Execute(CommandParameter);
      }
    }
  }
}

As always, when you know how to do it, it’s very simple. This method gets the AssociatedObject’s data context, the tries to find the getter of the Command property on this data context. As you might remember, a command in MVVMLight is defined like this:

public ICommand DoSomethingCommand
{
  get
  {
    return new RelayCommand<string>((p) =>
        {
          System.Diagnostics.Debug.WriteLine("Hi there {0}", p);
        });
  }
}

so I am not looking for a command method, but for a getter returning a command. If the code finds that, it tries to Invoke the getter as an ICommand. If it gets that it has the actual command, and it executes it. And that’s all!

So if you want to use this behavior, attach it to a Page’s main grid, for instance:

<Grid Style="{StaticResource LayoutRootStyle}" x:Name="TopView" x:Uid="TopGrid">
   <WinRtBehaviors:Interaction.Behaviors>
    <Win8nl_Behavior:EventToCommandBehavior Event="Tapped"
Command="DoSomethingCommand"
CommandParameter="John doe"/> </WinRtBehaviors:Interaction.Behaviors> <!--- stuff in here --> </Grid>

The top of your page needs to include this name space definitions:

xmlns:WinRtBehaviors="using:WinRtBehaviors"
xmlns:Win8nl_Behavior="using:Win8nl.Behaviors"

and then it will work. Tap on the main grid and you will see the text “Hi there John doe” in the Visual Studio output window. Of course you can make it do more useful things too ;-) and you can also bind things to the CommandParameter property using the normal binding syntax. To a certain extent.

You can download the behavior’s code here, but it's actually a lot easier to just use the NuGet Package. The behavior is there, along with some more nice stuff, and it takes care of downloading WinRtBehaviors and Reactive Extensions for WinRT as well

By special request I've also created sample code - not one but two solutions. The first one, TestWin8nl, is a very simple application that allows you to tap a TextBlock - this will trigger a command in the ViewModel that uses Debug.WriteLine to print a property of the ViewModel in your output console windows, using the CommandParameter to transfer the bound object (the ViewModel itself) to the command. The seconds sample, EventToCommandListDemo, will show you how to handle a SelectionChanged event of a ListBox, although frankly I'd rather just bind SelectedItem and act on it's property setter. But the audience asks, the audiences gets ;-). It appears tough as if Element name binding does not work properly in WinRtBehaviors, so I had to use a ViewModel property to store the selected item in anyway. Both are some contrived examples, but I hope the will do the trick of helping you out understanding how things are working and are supposed to be used.

Update: I have also blogged (and published in win8nl) a variant of the behavior that takes a bound command in stead of a command name. I personally now think this is a better solution as it adheres more to the way regular behaviors work, and is much more flexible Update 2: both this behavior and it's the bound-command-behavior are in the win8nl nuget package. Don't type, be lazy, use Nuget ;-)

23 July 2012

Using a provisional WinRT port of SilverlightSerializer to store state in MVVMLight ViewModels

Over 1.5 years ago I showed how to store your Windows Phone application state (‘tombstoning’) using SilverlightSerializer by Mike Talbot. In my quest to leverage hard-won Windows Phones skills to be usable in Windows 8 I made a provisional port of SilverlightSerializer 1 to WinRT. That is, in C#.

Since my win8nl library port is a bit behind, I’ve stuck the class in a simple project that you can download here.

Usage is as follows: in App.xaml.cs, you define two methods: SaveState and RestoreState:

private async void SaveState()
{
  var file = 
    await ApplicationData.Current.LocalFolder.CreateFileAsync(
      "AppState.dat", CreationCollisionOption.ReplaceExisting);

  using (var fileStream = await file.OpenStreamForWriteAsync())
  {
    SilverlightSerializer.Serialize(MainViewModel.Instance, fileStream);
  }
}

Pretty simple: when the state needs to be saved, create a file, get a stream, and let SilverlightSerializer do its magic. As for RestoreState:

private async Task RestoreState()
{
  try
  {
    var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
    var dataFile = files.FirstOrDefault(p => p.Name == "AppState.dat");
    if (dataFile != null)
    {
      using (var fileStream = await dataFile.OpenSequentialReadAsync())
      {
        MainViewModel.Instance = 
          SilverlightSerializer.Deserialize(fileStream.AsStreamForRead()) 
            as MainViewModel;
      }
    }
  }
  finally
  {
    if (MainViewModel.Instance == null) MainViewModel.CreateNew();
    MainViewModel.Instance.Start();
  }
}

This basically tries to deserialize a viewmodel from a file “AppState.dat”. If that fails, it creates a new MainViewModel, and starts it. The whole idea behind this is described in the original Windows Phone 7 post, so I encourage you to read that if you have no idea what I am doing here.

Now the important bit is when to call this methods. If you think the most logical place for RestoreState is in OnLaunched, you are right. The first few lines of my OnLaunced method in App.xaml.cs look like this in my app:

if (args.PreviousExecutionState == ApplicationExecutionState.Running)
{
  Window.Current.Activate();
  return;
}
else
{
  await RestoreState();
}

Now the most logical place to call SaveState is of course OnSuspending, and we are done, right?

Wrong.

To my own utter surprise, yesterday, after a long debugging session, I found a weird edge scenario. I asserted the following: if a user closes an app by the “Swipe Down gesture”, it takes about 10 seconds (on my Samsung Slate 7) before OnSuspending is called. When the user restarts the app within those 10 seconds from the start screen, the state is not stored yet, or too late – in any case it is not yet available to the (yet again) starting app. So you don’t get the last state, but the state before that, as I shamefully discovered when I proudly showed my state save method to an Application Excellence Lab Microsoftie :(

Don’t get me wrong – the actual time SaveState runs in my app is about 0.047 seconds. It’s lightning fast – just like the original SilverlightSerializer. But the time between user closing the app and the actual state save being fired up was killing my state.

The solution to this is very simple: when the user closes the app, Window.Current.VisibilityChanged is fired. Not like after a few seconds, but instantly. So add and event listener to that at the bottom of OnLaunched, that calls SaveState , like this:

 Window.Current.VisibilityChanged += (o, e) => {if (!e.Visible) SaveState();};

Basically: if the visibility of the current windows changes to invisible, write the state. Maybe you write app state too often (for example because the user temporarily puts it in the background, then VisibilityChanged is fired as well) but at least you circumvent the problem I ran into. Since state writing takes very little time, better often than not at all, I’d say.

And in OnSuspending? Well, you could call SaveState from there, too. That’s useful when your app does something in the background and it’s state changes even when the users has put it in the background. Then, when the OS kicks it into suspension because it runs out of memory, the state is saved too.

Caveat emptor: I kinda roughly hacked Mike Talbots work to operate in the WinRT world. The current state is ‘works for me’. I commented out the whole section about Dictionary support, so I suppose that does not work. My ultimate goal is to convert SilverlightSerializer 2, but that was too big a bone to chew in a short time. It serves my ported game Catch’em Birds fine. I hope to get it finished soon.

20 June 2012

Reflection in WinRT: use Rx Extensions for dynamically adding event handlers

Suppose you want to add an event handler, but you don’t know up front which event. Admittedly, this is a bit of an edge case, but I have used it in a behavior that starts a storyboard upon an event (I will publish that later). The designer can specify the event using a string value in XAML, so I cannot simply use object.MyEvent += (handler). We need reflection here.

So suppose you have found the event in the object using the GetRuntimeXXX methods like I described earlier today, and want to dynamically add a handler to the event “MyEvent”:

var evt = MyObject.GetType().GetRuntimeEvent("MyEvent");
evt.AddEventHandler(MyObject, 
  new EventHandler((p, q) => {// your code here }));

This will compile, and even run - unless the object is, for instance, a Grid, and the event “Loaded”. That’s apparently a “WinRT event”, whatever that may be, and this will result in a runtime exception:

"Adding or removing event handlers dynamically is not supported on WinRT events."

Googling Binging this message leads to all kind of complicated solutions using the WindowsRuntimeMarshall class (without any samples, alas), but the solution turns out to be very simple: use Rx Extensions Beta for Windows RT. For the really lazy reader: click tools/Library Package Manager/Package Manager Console and enter “Install-Package Rx-Main –Pre” in the Package Manager Console.

Now add

using System.Reactive.Linq;

to the top of the code file and then simply use the following code:

Observable.FromEventPattern<RoutedEventArgs>(MyObject, "MyEvent")
  .Subscribe(se => { // your code here });

and you are done. The difference between ordinary events and “WinRT events” is apparently swallowed up in the bowels of Rx. This library is great to begin with, but if it saves you the trouble of digging in yet another still not very thoroughly documented API, it’s even better. As a bonus, by very nature of Rx the handler is automatically disposed of when your calling object goes out of scope, which is not necessarily the case in my first code. But that did not work anyway ;-)

Reflection in WinRT: DeclaredProperties vs GetRuntimeProperties caveat

I suppose this is part of some FM I did not R, but I would like to point it out in case some other sod wastes just as much time on it as me.

I embarked upon a journey to port SilverlightSerializer and some behaviors to WinRT. All stuff is heavily making use of reflection. Now reflection has been hugely overhauled in WinRT, so I knew I was in for an interesting ride. Recently I was convinced I managed to do it, but it turned out I did not.

There are apparently two ways to use reflection in RT. What I did use for reading all properties of an object, was:

var properties = MyObject.GetType().GetTypeInfo().DeclaredProperties;

But it turns out this returns only the properties declared in the class itself. What it does not return, are the properties of possible parent classes!

What I should have used, apparently, is:

var allproperties = MyObject.GetType().GetRuntimeProperties();

When I feed a Grid into “MyObject”,  “properties” hold 6 properties, while “allproperties” holds 51.

I don’t know why this distinction is made, and I understand even less how come I missed this the first time. On my first meeting as an MVP, Dennis Vroegop, after welcoming me to the club, already warned me that the MVP award did not automatically come with super powers. Boy, was he right.

14 June 2012

NavigationService for WinRT

"If I have been able to see further than others, it is because I have stood on the shoulders of giants."
 Isaac Newton

It was only 1.5 years ago, but it seems already a long time ago that Laurent Bugnion described a “view service” for Windows Phone navigation, commonly know as the NavigationService. I’ve incorporated this code in my #wp7nl library on codeplex and have been using it happily ever since (and a lot of other people I know have been doing so as well), Time goes on, along came Windows 8 and WinRT and Metro Style Apps.

Laurent ported his MVVMLight framework to WinRT as well. But the NavigationService never has been a core part of MVVMLight (therefore I put it in the #wp7nl library) and porting it to WinRT as well proved to be a bit of a hassle. Some of its premises where no longer valid – most notable the way to retrieve the main application frame by accessing Application.Current.RootVisual, which does not work in WinRT. I messed around a little with the code, did not get anywhere, and left it there. So I was glad I saw my fellow Windows Phone Development MVP Matteo Pagani tweet he got a NavigationService to work. He was kind enough to mail me the code. He basically copied the code from Windows Phone and made the apps rootFrame, as created in the App.xaml.cs, publicly available. A neat trick, with as only drawback that you have to copy the code to every app. As things goes, it’s usually easier to see someone else’s idea and improve it, than think it up out of the blue. I toyed around with it and managed to get rid of the need to copy the code, so I could put it in a library.

And here it is, an improved version of a NavigationService for WinRT, based upon Matteo’s code based upon Laurent’s code ;-)

First of all, the NavigationService’s interface:

using System;
using Windows.UI.Xaml.Navigation;

namespace Win8nl.Services
{
  public interface INavigationService
  {
    event NavigatingCancelEventHandler Navigating;
    void Navigate(Type type);
    void Navigate(Type type, object parameter);
    void Navigate(string type);
    void Navigate(string type, object parameter);
    void GoBack();
  }
}

This quite looks like the old interface, with some notable exceptions. First of all, the NavigateTo method is renamed Navigate, to mimic the method name used in WinRT itself. And it has not one but four overloads. The first two are pretty logical – WinRT does not use an uri for navigation, but an actual Type object, making strongly-typed navigation possible. And it supports an overload for a parameter object, as well. The two other methods, with the string type object… well see for yourself below, in the implementation of the service:

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace Win8nl.Services
{
  public class NavigationService : INavigationService
  {
  public NavigationService(Frame mainFrame)
  {
    _mainFrame = mainFrame;
  }

  private Frame _mainFrame;
  
  public event NavigatingCancelEventHandler Navigating;

  public void Navigate(Type type)
  {
    _mainFrame.Navigate(type);
  }

  public void Navigate(Type type, object parameter)
  {
    _mainFrame.Navigate(type, parameter);
  }

  public void Navigate(string type, object parameter)
  {
    _mainFrame.Navigate(Type.GetType(type), parameter);
  }

  public void Navigate(string type)
  {
    _mainFrame.Navigate(Type.GetType(type));
  }

  public void GoBack()
  {
    if (_mainFrame.CanGoBack)
    {
      _mainFrame.GoBack();
    }
  }  
}

So the string type methods allow you to specify the page to navigate by string. Before you all think I really lost my marbles this time, re-introducing weakly typed navigation just as the Windows team introduced strongly typed: I specifically added this as to allow navigation to be initiated from a ViewModel contained in an assembly not containing the XAML code. This also enables you to test code as well. This is the way I built my solutions for Windows Phone, and I intend to go on this way in Windows 8. ;-)

Anyway, there’s a thing missing in this code: the EnsureMainFrame that looked up the root page, for which Matteo used a public property. I completely removed it, and added a constructor accepting that root page. By creating that constructor I deleted the default constructor, so registering the NavigationService at he SimpleIoc container shipped with MVVMLight in the App.xaml.cs, like this:

SimpleIoc.Default.Register<INavigationService, Wp7nl.Utilities.NavigationService>();

as we did in Windows Phone code, won’t work anymore. Fortunately, SimpleIoc also supports factory methods to create an instance. So now you go to the App.xaml.cs of your Windows 8 app, find the OnLaunched method and just behind this line:

var rootFrame = new Frame();

you add this piece of code:

SimpleIoc.Default.Register<INavigationService>(() => 
                                   {return new NavigationService(rootFrame);});

Now if your XAML code and ViewModels are all in one assembly, you can call the NavigationService to navigate to the main page this:

SimpleIoc.Default.GetInstance<INavigationService>().Navigate(typeof(MainPage));

or if you are a bit stubborn like me and would like to separate ViewModels and views, you can use the string overload to specify the full qualified name and for instance use it in a ViewModel command like this

public ICommand TestNavigatieCommand
{
   get
   {
     return new RelayCommand(() => 
       SimpleIoc.Default.GetInstance<INavigationService>().Navigate("MyApp.MainPage,MyApp"));
   }
}

And there you have, a fully functional NavigationService for Windows 8. Code can be downloaded here. I will soon incorporate it in the provisional port of the #wp7nl library called win8nl.

Thanks to Laurent and Matteo for being my trailblazers ;-)

Behavior to make Bing Maps view area bindable

The Bing Maps control in Windows Phone 7 is pretty versatile but does not always play along very well with data binding. You can bind ZoomLevel and MapCenter, which is all very well, but if you want to know what area is actually shown within the map – for instance, for making a GIS application that loads only visible data, and not stuff that’s outside the view area anyway, things get a lit complicated.

Not so if you uses this little behavior. It builds upon the SafeBehavior that is already in my wp7nl library on codeplex. It sports two GeoCoordinate depencency propertise, NorthEast and SouthWest

using System.Device.Location;
using System.Windows;
using Microsoft.Phone.Controls.Maps;

namespace Wp7nl.Behaviors
{
  public class ViewportAreaBehavior
  {
    /// <summary>
    /// A behavior to make southwest and northeast bindable
    /// </summary>
    public class ViewportwatcherBehavior : SafeBehavior<Map>
    {
      #region NorthWest
      public const string NorthWestPropertyName = "NorthWest";

      public GeoCoordinate NorthWest
      {
        get { return (GeoCoordinate)GetValue(NorthWestProperty); }
        set { SetValue(NorthWestProperty, value); }
      }

      public static readonly DependencyProperty NorthWestProperty = 
	DependencyProperty.Register(
          NorthWestPropertyName,
          typeof(GeoCoordinate),
          typeof(ViewportwatcherBehavior),
          new PropertyMetadata(null));

      #endregion

      #region SouthEast
      public const string SouthEastPropertyName = "SouthEast";

      public GeoCoordinate SouthEast
      {
        get { return (GeoCoordinate)GetValue(SouthEastProperty); }
        set { SetValue(SouthEastProperty, value); }
      }

      public static readonly DependencyProperty SouthEastProperty = 
	DependencyProperty.Register(
          SouthEastPropertyName,
          typeof(GeoCoordinate),
          typeof(ViewportwatcherBehavior),
          new PropertyMetadata(null));

      #endregion
    }
  }
}

All pretty standard stuff. Next comes the setup/cleanup stuff,

protected override void OnSetup()
{
  AssociatedObject.ViewChangeEnd += AssociatedObjectViewChangeEnd;
  CalcRectangle();
}

protected override void OnCleanup()
{
  AssociatedObject.ViewChangeEnd -= AssociatedObjectViewChangeEnd;
}

in which you can see I intercept the ViewChangeEnd event. I don’t do anything special there: I just call the method CalcRectangle, just as on startup.

void AssociatedObjectViewChangeEnd(object sender, MapEventArgs e)
{
  CalcRectangle();
}

The final missing piece of the puzzle is then of course CalcRectangle itself:

private void CalcRectangle()
{
  NorthWest = AssociatedObject.ViewportPointToLocation(new Point(0, 0));
  SouthEast = AssociatedObject.ViewportPointToLocation(
    new Point(AssociatedObject.ViewportSize.Width, 
              AssociatedObject.ViewportSize.Height));
}

So I basically take the point left top (0,0) and and use ViewportPointToLocation to convert it to a coordinate, and do the same think with the point that left bottom. And that’s all.

Now you can bind to the NorthWest and SouthEast property of the behavior and you get the view area in your view model. Be aware this works one way. It gets the view area to the ViewModel, not the other way around.

Contrary to my custom there’s no solution with the code in it, mostly because it’s already in the wp7nl library since yesterday. You can download the code from the library itself here, if you want.

06 June 2012

Detecting your Windows 8 app is running in the background

In Windows Phone life was so simple: when the user put your app in the background, as of version 7.5 the OS effectively froze all threads, timers and whatnot completely automatically. And it was automatically restarted too, if you used fast application switching. That kind of freeloading appeals to my natural programmer’s laziness so I put that to good use. That is, by doing nothing and letting the OS taking care of things.

Enter Windows 8: that has a even more sophisticated multi tasking system that allows things to actually keep running in the background. Excellent for most scenarios, but not if you are writing a game. I am currently porting Catch’em Birds to Windows 8 and observed that although the game music (thankfully) shuts up when the game is put in the background, the birds keep on flying and the timer keeps on running.

Now in App.Xaml.cs there is an OnSuspending method, but that is only called when the application is suspended – i.e., pushed out of memory. This is comparable to the point where a Windows Phone application would tombstone itself. You need to trap another event: VisibilityChanged of the current window.

In the OnLaunchedmethod of App.Xaml.cs, just above the Window.Current.Activate you can add

Window.Current.VisibilityChanged += Current_VisibilityChanged;
That gives a Windows.UI.Core.VisibilityChangedEventArgs which has a boolean Visible property that you can use like this:
void Current_VisibilityChanged(object sender, 
                               Windows.UI.Core.VisibilityChangedEventArgs e)
{
  System.Diagnostics.Debug.WriteLine("Visibile: " + e.Visible);
}

I am going to use this to send this event trough the MVVMLight messenger and adapt my game so that is reacts to this event – like in ‘stop the birds, or at least the timer. The OS being more capable actually requires me to do a wee bit more work. No more freeloading ;-)