Nico's digital footprint

I grew up in the nineties, that makes me awesome by default

Geofencing in Windows Phone 8.1

by Nico

Windows Phone 8.1 brings the concept of Geofencing to our beloved Windows Phone platform. Geofencing allows us to trigger an action whenever a user is at a predefined set of coordinates. Windows Phone 8.1 registers geofences with the OS so our app doesn’t need to run for triggers to fire. For this post we’ll trigger a welcome message whenever someone is at building 9 of the Microsoft Redmond campus.

The app

Create a new Windows Phone 8.1 app. Add the Location capability in the Package.appxmanifest. We obviously need location capabilities for this Glimlach

Let’s dive into code. This app will only have a blank MainPage and a message dialog that pops up when we’re near building 9.

First thing we need is a reference to the current GeofenceMonitor.

Code Snippet
  1. GeofenceMonitor _monitor = GeofenceMonitor.Current;

Setting the Geofence location and hooking up the event happens in the constructor

Code Snippet
  1. public MainPage()
  2. {
  3.     InitializeComponent();
  4.  
  5.     _monitor.GeofenceStateChanged += MonitorOnGeofenceStateChanged;
  6.  
  7.     //Microsoft Redmond building 9
  8.     BasicGeoposition pos = new BasicGeoposition { Latitude = 47.6397, Longitude = -122.1289 };
  9.  
  10.     Geofence fence = new Geofence("building9", new Geocircle(pos, 100));
  11.  
  12.     try
  13.     {
  14.         _monitor.Geofences.Add(fence);
  15.     }
  16.     catch (Exception)
  17.     {
  18.         //geofence already added to system
  19.     }
  20. }

First we hook up the GeofenceStateChanged event, we’ll look at the eventhandler in a minute. Then we create a BasicGeoPosition which holds the coordinates for, in our case, building 9 of the Microsoft campus in Redmond. Then we create a Geofence. The Geofence constructor takes two parameters, a string that functions as ID so it should be unique, and an IGeoShape. Other overloads for Geofence allow us to specify if we want to trigger the event whenever we enter or leave the geofence area.

For the ID we use a string, for the IGeoShape we use a GeoCircle. Other build-in possibilities are

  • Geoboundingbox
  • Geocircle
  • Geopath
  • Geopoint

The Geocircle takes two parameters, the position and the radius (in meters). We’ve already defined a position as BasicGeoposition, which is exactly the type expected by the Geocircle, and we define a radius of 100 meters. Finally we try to add the Geofence to the geofences registered in the OS. If a Geofence with the same ID already exists it will throw an exception stating that the object already exists.

Let’s have a look at the event handler

Code Snippet
  1. private void MonitorOnGeofenceStateChanged(GeofenceMonitor sender, object args)
  2. {
  3.     var fences = sender.ReadReports();
  4.  
  5.     foreach (var report in fences)
  6.     {
  7.         if (report.Geofence.Id != "building9")
  8.             continue;
  9.  
  10.         switch (report.NewState)
  11.         {
  12.             case GeofenceState.Entered:
  13.                 Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
  14.                 {
  15.                     MessageDialog dialog = new MessageDialog("Welcome to building 9");
  16.  
  17.                     await dialog.ShowAsync();
  18.                 });
  19.                 break;
  20.             case GeofenceState.Exited:
  21.                 Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
  22.                 {
  23.                     MessageDialog dialog = new MessageDialog("Leaving building 9");
  24.  
  25.                     await dialog.ShowAsync();
  26.                 });
  27.                 break;
  28.         }
  29.     }
  30. }

Before we can show a message we’ll need to know what geofence triggered the event. We do that by calling ReadReports on the GeofenceMonitor. This method will return a ReadOnlyList containing GeofenceStateChangedReports. Iterating over those reports we can check the ID of the geofence and take action when the expected geofence is triggered. In this case we want to show a welcome message when someone arrives and a leaving message when someone leaves. Let’s try it out!

Launch the app in the emulator (unless you’re physically at building 9, then you can use a WP8.1 device Glimlach), open the emulator tools and set the location to building 9. You’ll have to wait some seconds before the message pops up, this is to prevent triggers being fired when just passing through a geofence location. You can manipulate this delay by using an overload of the Geofence constructor and setting the DwellTime parameter (TimeSpan).

Clear your location and set it somewhere away from building 9, wait a few seconds and watch the leaving message.

Conclusion

Geofencing is a pretty cool way to interact with users based on their location. It’s a great addition to the platform and personally I can’t wait to see what great ideas devs will come up with to use this functionality.

In this post I did a quick, basic lap around geofencing. Geofences can also trigger a backgroundtask, provided the app is set as lockscreen app, so the app doesn’t need to run all the time for geofencing to do its stuff.

As usual, the code can be found on my OneDrive


Tags:

WinRT | WP8 | geofencing

Building a REST API and consuming it in WP8

by Nico

As a mobile developer we often need to consume some API in order to get data. In a lot of cases that API is made available to us by some third party, for example Twitter, Facebook, Flickr, ...  However, in some cases we are ourselves responsible for the data. In order to get the data from our datastore to our app we’ll need to build an API. In this article I’ll walk you through creating a basic API with the CRUD operations and consume it in a Windows Phone app.

For this post I’ll be using

  • ASP.NET WebApi 2.1
  • Visual Studio 2013
  • Microsoft Azure Websites
  • Windows Phone

The API will be build in WebApi 2.1 and hosted on Azure Websites. I’ve chosen Azure Websites because they offer 10 free websites and have great integration in Visual Studio 2013 update 1. Feel free to choose any other webhost, as long as they support MVC 5 you should be fine.

Setting up the API project

All right, let’s get started by building the API. In Visual Studio 2013 select File > New Project > Web > ASP.NET Web Application. In the next window, select Web API. If you’re deploying to Azure, check the “Create remote resources” box. This will create either an Azure Website or an Azure Virtual Machine for you. We’re not doing any authentication for this post, I’m saving that for a future post Glimlach, so leave it at No Authentication and click OK.

Visual Studio will create your project, tell Azure to create a Website and setup publish profiles for you. If you run this project you’ll get an ASP.NET MVC application with the default template but underneath it has also fired up a WebAPI. If you click the API link in the default template it will show you all available API calls (the WebApi template has a demo controller to get you started).

Now, for our API we’re going to create a database that holds famous quotes. Nothing fancy, just a database with one table that holds quotes. This is the Quote class

Code Snippet
  1. public class Quotes
  2. {
  3.     public int ID { get; set; }
  4.     public string Quote { get; set; }
  5. }

Time to add our API controller. If you’re familiar with MVC then this will look very familiar. WebAPI is basically MVC without the V. You have Models, you have controllers but instead of returning a view, the controllers return a Rest result, by default in JSON.

Right-click the controllers folder > Add > Controller. Select “Web API 2 controller with actions, using Entity Framework”. In the Model class dropdown select the Quotes class we’ve just created. The Data context drop down is where we can select our Entity framework context but that hasn’t been created yet. Click the + button next to the dropdown, select a name and click Add. Now we do have a context. Click Add and let Visual Studio create your Controller for you.

The newly created controller features all CRUD operations using the context we’ve just created to get to our Entity Framework. Before testing this, have a look in the Web.config file. You should find something like this not far from the top of the file

Code Snippet
  1. <connectionStrings>
  2.   <add name="RestDemoContext" connectionString="Data Source=(localdb)\v11.0; Initial Catalog=RestDemoContext-20140327114532; Integrated Security=True; MultipleActiveResultSets=True; AttachDbFilename=|DataDirectory|RestDemoContext-20140327114532.mdf"
  3.     providerName="System.Data.SqlClient" />
  4. </connectionStrings>

This is the database connection that Entity Framework will use. It’s currently set to a local SQL Express database but a SQL Azure database has been created together with our project when we were first setting it up, so we’ll need to change this. Login to the Azure portal and go to Databases, find the created database for your project and select  “View SQL Database connection strings for ADO .Net, ODBC, PHP, and JDBC”.

Copy the ADO.NET connectionstring and paste it into the Web.config so that the line from before now looks like this

Code Snippet
  1. <connectionStrings>
  2.   <add name="RestDemoContext" connectionString="Server=tcp:tvez9dpih8.database.windows.net,1433;Database=RestDemo_db;User ID={Your_userID_here};Password={your_password_here};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
  3.     providerName="System.Data.SqlClient" />
  4. </connectionStrings>

Don’t forget to fill in your correct user ID and password. If you’ve set everything up, it’s time to try this out. Launch the project and navigate to the API link from the page header. It should now show you all available actions from your new controller. Click on the POST entry from the Quotes controller. This page shows you how a body from a POST request to this controller should look like. Let’s try it out in Fiddler.

Open Fiddler while your project is still running and go to the Composer tab. Set the method to POST from the dropdown and enter the url to your API endpoint. In my case this was http://localhost:36264/api/quotes. In the request headers field add this line

Content-Type: application/json

This will tell our API that the body contains JSON formatted data. In the request body we can copy/paste the sample data that the API page from the project gave us and fill in some nice quote.

{
  "ID": 1,
  "Quote": "you have failed me for the last time"
}

Click Execute and after a few seconds Fiddler should show a 201 result. HTTP code 201 means “Created” so our post was successful. Change the method to GET, clear the body and click execute again. Fiddler should show a 200. Select that line and the Inspectors Tab to see the result.

 

A closer look

Let’s take a closer look at the API methods.

Code Snippet
  1. // GET: api/Quotes/5
  2. [ResponseType(typeof(Quotes))]
  3. public async Task<IHttpActionResult> GetQuotes(int id)
  4. {
  5.     Quotes quotes = await db.Quotes.FindAsync(id);
  6.     if (quotes == null)
  7.     {
  8.         return NotFound();
  9.     }
  10.  
  11.     return Ok(quotes);
  12. }

The first line is a comment (obviously Glimlach) that shows you how to call this method. The second line is an attribute to specify the expected content type in the response. Skip ahead to lines 8 and 11. These are helper methods found in the ApiController base class. When called they create a response with the correct HTTP code, 404 for not found or 200 for ok in this case, and set the content of the response.

We could add a second attribute to this method called HttpGet. Each of the verbs (GET, PUT, POST, DELETE) have an attribute version. You can use them freely here but the default template is working with a convention. Every method where the name starts with Get will be a GET method by default, the same for PUT, POST and DELETE.

Publish to Azure Websites

Publishing to your Azure website is as easy as right-clicking your web project (NOT the solution) and selecting publish. Let Visual Studio do its thing, your browser will open and your API is live on the internet. We can even debug live on the azure website by opening Server Explorer in Visual Studio > Azure > Websites > right-click your site > Attach Debugger (note that this works best when you deployed a debug build of your site.

Creating the app

Time to consume our fancy API. Create a new blank Windows Phone 8 application and add the following Nuget packages

  • Install-Package Microsoft.Net.Http
  • Install-Package Newtonsoft.Json
  • Install-Package MvvmLight

So what are these for? The first one gives us the HttpClient class which is a far superior way to do HTTP requests in Windows Phone than any class included in the SDK. It’s also a portable library so it makes your code very easy to port over to other platforms. Json.net because we’ll receive a JSON response from our API and we need to deserialize it back to an object. And MVVM Light because I just can’t live without it.

Getting data

We’ll start by requesting all quotes currently in the database. First, add the Quotes class from the API project to the phone project. Second, add a LongListSelector to the MainPage

Code Snippet
  1. <phone:LongListSelector ItemsSource="{Binding Quotes}">
  2.     <phone:LongListSelector.ItemTemplate>
  3.         <DataTemplate>
  4.             <TextBlock Style="{StaticResource PhoneTextNormalStyle}" Text="{Binding Quote}" />
  5.         </DataTemplate>
  6.     </phone:LongListSelector.ItemTemplate>
  7. </phone:LongListSelector>

Next, in the MainViewModel we’ll fetch the data and set it to Quotes (don’t forget to set MainViewModel as datacontext of MainPage).

Code Snippet
  1. private ObservableCollection<Quotes> _quotes;
  2.  
  3. public ObservableCollection<Quotes> Quotes
  4. {
  5.     get { return _quotes; }
  6.     set
  7.     {
  8.         if (_quotes == value) return;
  9.  
  10.         _quotes = value;
  11.         RaisePropertyChanged(() => Quotes);
  12.     }
  13. }
  14.  
  15. /// <summary>
  16. /// Initializes a new instance of the MainViewModel class.
  17. /// </summary>
  18. public MainViewModel()
  19. {
  20.     FetchQuotes();
  21. }
  22.  
  23. private async Task FetchQuotes()
  24. {
  25.     using (HttpClient client = new HttpClient())
  26.     {
  27.         var result = await client.GetAsync("http://restdemo.azurewebsites.net/api/quotes");
  28.  
  29.         result.EnsureSuccessStatusCode();
  30.  
  31.         Quotes = new ObservableCollection<Quotes>(JsonConvert.DeserializeObject<IEnumerable<Quotes>>(await result.Content.ReadAsStringAsync()));
  32.     }
  33. }

Quotes is an ObservableCollection of type Quotes. FetchQuotes does all the heavy lifting here and is called upon initialization of the MainViewModel. It creates an instance of HttpClient (in a using statement, because HttpClient implements IDisposable). It calls our API endpoint that returns all quotes from the database. When it’s done fetching data we call EnsureSuccessStatusCode on the result. This method will throw an error if the returned HTTP code is not a success code, for example when we should receive a not found or bad request error. If everything went well we can read the result.Content as a string, this will give us the quotes in a JSON string format. We feed it into JSON.net his deserializer and we’re done!

Now what good is having our own API when all we do is reading from it? Time to post some quotes! Add a second page and a way to navigate to that page. To keep things simple I’ve hooked this AddPage up to MainViewModel as datacontext. So I have 2 pages and 1 viewmodel. In the Viewmodel I create a new property that will hold the new quote.

Code Snippet
  1. public Quotes NewQuote
  2. {
  3.      get { return _newQuote; }
  4.      set
  5.      {
  6.          if (_newQuote == value) return;
  7.  
  8.          _newQuote = value;
  9.          RaisePropertyChanged(() => NewQuote);
  10.      }
  11. }

The page contains a textbox that has a two-way binding to this property

Code Snippet
  1. <StackPanel x:Name="ContentPanel"
  2.             Grid.Row="1"
  3.             Margin="12,0,12,0">
  4.     <TextBlock Style="{StaticResource PhoneTextNormalStyle}" Text="Quote" />
  5.     <TextBox Text="{Binding NewQuote.Quote, Mode=TwoWay}" />
  6. </StackPanel>

And to glue things together, there’s a save method in the Viewmodel that will POST this new quote to the API, clear the NewQuote property and refetch all properties, including the one we just saved.

Code Snippet
  1. public async Task SaveQuote()
  2. {
  3.     using (HttpClient client = new HttpClient())
  4.     {
  5.         HttpContent content = new StringContent(JsonConvert.SerializeObject(NewQuote));
  6.         content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  7.  
  8.         var result = await client.PostAsync("http://restdemo.azurewebsites.net/api/quotes", content);
  9.  
  10.         result.EnsureSuccessStatusCode();
  11.     }
  12.  
  13.     NewQuote = new Quotes();
  14.     await FetchQuotes();
  15. }

To do a POST we first need to prepare the content. In our case we’re going to send a JSON string so we need to convert our NewQuote into JSON and put it inside StringContent. Next step is setting the ContentType in the header, just like we did when using Fiddler a few steps ago. Call PostAsync on the HttpClient, ensure its success and we’re done. If all went well the api saved the quote, the app refetched all quotes and the new one should show up on the MainPage.

Conclusion

In this article I’ve shown the steps needed to build and consume a basic REST API using ASP.net WebApi and Windows Phone 8. The code from the WP8 app is very generic and can be used on a lot of platforms, even for platforms where HttpClient isn’t available, the way of working, the headers, the expected HTTP codes, should all be the same.

The code for both the API and the app can be found on my OneDrive.


Tags:

.Net | Azure | Data | WP8 | WinRT | REST

WP8 as bluetooth Start button

by Nico

If you’ve ever used applications like the Office Remote that seem to take over your computer you’ll know that it can provide quite the “magic” experience. As with all magic technologies this one is quite simple as well. All we need is a computer with Bluetooth that runs a small app with a Bluetooth listener and a Windows Phone app that connects to that listener app via Bluetooth. For this demo app I’m going to make the Windows Phone app act like the Start button on a Windows machine.

Simulating the Windows key

The listener application is a small WPF app that has only one button. That button will act like the Start button. To interact with the operating system and simulate a keyboard press we’ll need to import user32.dll and hook into its keybd_event. We’ll want to send ctrl + esc to Windows (acts the same as the Windows key)

Code Snippet
  1. //source: http://www.codeproject.com/Questions/46731/Open-Start-Menu
  2. private static void ShowStartMenu()
  3. {
  4.     // key down event:
  5.     const byte keyControl = 0x11;
  6.     const byte keyEscape = 0x1B;
  7.     keybd_event(keyControl, 0, 0, UIntPtr.Zero);
  8.     keybd_event(keyEscape, 0, 0, UIntPtr.Zero);
  9.  
  10.     // key up event:
  11.     const uint keyeventfKeyup = 0x02;
  12.     keybd_event(keyControl, 0, keyeventfKeyup, UIntPtr.Zero);
  13.     keybd_event(keyEscape, 0, keyeventfKeyup, UIntPtr.Zero);
  14. }
  15.  
  16. [DllImport("user32.dll")]
  17. static extern void keybd_event(byte bVk, byte bScan, uint dwFlags,
  18.    UIntPtr dwExtraInfo);

In the event handler of the button we call ShowStartMenu() and behold: a wild software Windows key appears!

Building the Bluetooth listener

Adding Bluetooth support to a .NET application isn’t the easiest thing to do. Luckily for us there are libraries out there that take out the hassle. For this project I used Peter Foot’s 32feet.NET library available through NuGet

Install-Package 32feet.NET

A small note on this package as found on the 32feet.NET product page

“Bluetooth support requires a device with the Microsoft or Widcomm Bluetooth stack”

Luckily for me, my device uses the Microsoft BT stack, so I’m good to go. Now on to the code, we’ll need to start a BT listener and once connected read data from a networkstream. If we receive a certain message we’ll execute the ShowStartMenu() method.

First some fields

Code Snippet
  1. private BluetoothListener _listener;
  2.  
  3. //unique service identifier
  4. private readonly Guid _service = new Guid("{7A51FDC2-FDDF-4c9b-AFFC-98BCD91BF93B}");
  5. private bool _connected;

BluetoothListener is a class we get from 32feet.NET. The GUID is a reference to the service this app is providing, our Windows Phone app will need the same GUID to be able to connect to this service. And the third field is a boolean to keep track of having a connected client or not.

Code Snippet
  1. private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
  2. {
  3.     BluetoothRadio br = BluetoothRadio.PrimaryRadio;
  4.  
  5.     if (br == null)
  6.     {
  7.         MessageBox.Show("No supported Bluetooth radio/stack found.");
  8.     }
  9.     else if (br.Mode != RadioMode.Discoverable)
  10.     {
  11.         MessageBoxResult rslt = MessageBox.Show("Make BluetoothRadio Discoverable?",
  12.             "Bluetooth Remote Listener", MessageBoxButton.YesNo);
  13.  
  14.         if (rslt == MessageBoxResult.Yes)
  15.         {
  16.             br.Mode = RadioMode.Discoverable;
  17.         }
  18.     }
  19.  
  20.     _listener = new BluetoothListener(_service);
  21.     _listener.Start();
  22.  
  23.     System.Threading.Thread t = new System.Threading.Thread(ListenLoop);
  24.     t.Start();
  25. }

In the OnLoaded event from the MainWindow we’ll first check if there’s a BT radio found that works on the MS or Widcomm stack. If that’s found, and made discoverable, we’ll start the listener with the service GUID specified in the field. Once the listener is started we fire up a second thread that will contain a loop to connect a client and read data from the stream.

Code Snippet
  1. private void ListenLoop()
  2. {
  3.     byte[] buffer = new byte[1024];
  4.  
  5.     while (true)
  6.     {
  7.         BluetoothClient bc;
  8.         Stream ns;
  9.  
  10.         try
  11.         {
  12.             bc = _listener.AcceptBluetoothClient();
  13.             ns = bc.GetStream();
  14.             _connected = true;
  15.         }
  16.         catch
  17.         {
  18.             break;
  19.         }
  20.  
  21.         //keep connection open
  22.         while (_connected)
  23.         {
  24.             try
  25.             {
  26.                 int received = ns.Read(buffer, 0, buffer.Length);
  27.  
  28.                 if (received > 0)
  29.                 {
  30.                     string data = Encoding.UTF8.GetString(buffer);
  31.  
  32.                     string command = data.Substring(0, data.IndexOf("\0", StringComparison.Ordinal));
  33.  
  34.                     if (command == "Start")
  35.                     {
  36.                         ShowStartMenu();
  37.                     }
  38.                 }
  39.                 else
  40.                 {
  41.                     //connection lost
  42.                     _connected = false;
  43.                 }
  44.             }
  45.             catch
  46.             {
  47.                 _connected = false;
  48.                 break;
  49.             }
  50.         }
  51.  
  52.         try
  53.         {
  54.             bc.Close();
  55.         }
  56.         catch
  57.         {
  58.         }
  59.     }
  60. }

This is the code for the loop that runs in the second thread. First we declare a buffer of 1KB, more than enough for this sample. Next we start an infinite loop, in that loop we declare a BluetoothClient and a Stream. Once a client connects through the AcceptBluetoothClient method we fetch a stream and set the connected flag to true. As long as we’re connected we read data from the stream into the buffer, once we receive actual data we’ll decode it from a byte array (the buffer) into a string (the original message). In this sample the message will be 5 bytes but the buffer can hold 1024 bytes. It will fill up the remaining bytes with “\0” so we’ll need to chop that of with a Substring. If the received string is “Start” we’ll flip to the Start screen. If we read from the stream but the number of received bytes is zero, we’ve lost the connection to the client.

Fire up the WPF app, make sure the button flips you to the Start screen and let’s get started on the WP8 app!

Windows Phone Client

The Windows Phone app consists of two pages. The MainPage is for selecting a Bluetooth peer to connect to and the ConnectedPage has the same button as the WPF application. The app uses MVVM Light, everything happens in the MainViewModel. Both the MainPage and ConnectedPage use MainViewModel as their datacontext. For navigation I’ve added the always helpful Cimbalino NuGet package and registered their NavigationService in SimpleIoc through the ViewModelLocator

Code Snippet
  1. public ViewModelLocator()
  2. {
  3.     ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
  4.  
  5.     if (ViewModelBase.IsInDesignModeStatic)
  6.     {
  7.         // Create design time view services and models
  8.     }
  9.     else
  10.     {
  11.         // Create run time view services and models
  12.         SimpleIoc.Default.Register<INavigationService, NavigationService>();
  13.     }
  14.  
  15.     SimpleIoc.Default.Register<MainViewModel>();
  16. }

In the MainViewModel I have declared three properties

Code Snippet
  1. private ObservableCollection<PeerInformation> _peers;
  2. private PeerInformation _selectedPeer;
  3. private ICommand _goToStartCommand;
  4.  
  5. public ICommand GoToStartCommand
  6. {
  7.     get { return _goToStartCommand ?? (_goToStartCommand = new RelayCommand(SendCommand)); }
  8. }
  9.  
  10. public ObservableCollection<PeerInformation> Peers
  11. {
  12.     get { return _peers; }
  13.     set
  14.     {
  15.         if (_peers == value) return;
  16.  
  17.         _peers = value;
  18.         RaisePropertyChanged(() => Peers);
  19.     }
  20. }
  21.  
  22. public PeerInformation SelectedPeer
  23. {
  24.     get { return _selectedPeer; }
  25.     set
  26.     {
  27.         if (_selectedPeer == value) return;
  28.  
  29.         _selectedPeer = value;
  30.         RaisePropertyChanged(() => SelectedPeer);
  31.  
  32.         ConnectToDevice();
  33.     }
  34. }

The PeerInformation class is something we get from the Windows Phone Bluetooth API. We have an observablecollection that will hold all peers that are known for your Windows Phone device, we also have a property for the selected peer and a command that will fire a message into the NetworkStream.

We’ll also need some fields

Code Snippet
  1. private StreamSocket _socket;
  2. private DataWriter _dataWriter;
  3.  
  4. private readonly INavigationService _navigationService;

The socket will hold the connection between the phone app and the WPF app. The DataWriter can write data into the stream. The NavigationService is the one from the Cimbalino toolkit.

Here’s the constructor for the MainViewModel

Code Snippet
  1. public MainViewModel(INavigationService navigationService)
  2. {
  3.     if (IsInDesignModeStatic) return;
  4.  
  5.     _navigationService = navigationService;
  6.  
  7.     if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Emulator)
  8.     {
  9.         MessageBox.Show("Bluetooth not available in the emulator");
  10.     }
  11.     else
  12.     {
  13.         RefreshPairedDevicesList();
  14.     }
  15. }

The NavigationService is injected via SimpleIoc. First we check if the current device is the Windows Phone emulator, the emulator doesn’t support Bluetooth so we need an actual device to test this on.

The RefreshPairedDevicesList looks like this (all using the Windows Phone Bluetooth APIs)

Code Snippet
  1. private async void RefreshPairedDevicesList()
  2. {
  3.     try
  4.     {
  5.         // Search for all paired devices
  6.         PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
  7.         var peers = await PeerFinder.FindAllPeersAsync();
  8.  
  9.         Peers = new ObservableCollection<PeerInformation>(peers);
  10.     }
  11.     catch (Exception ex)
  12.     {
  13.         if ((uint)ex.HResult == 0x8007048F)
  14.         {
  15.             if (MessageBox.Show("Bluetooth is off, enable it?",
  16.                 "Bluetooth Off", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
  17.             {
  18.                 ConnectionSettingsTask connectionSettingsTask = new ConnectionSettingsTask
  19.                 {
  20.                     ConnectionSettingsType = ConnectionSettingsType.Bluetooth
  21.                 };
  22.                 connectionSettingsTask.Show();
  23.                 RefreshPairedDevicesList();
  24.             }
  25.         }
  26.         else
  27.         {
  28.             MessageBox.Show(ex.Message);
  29.         }
  30.     }
  31. }

First we’ll look for all paired devices for our phone, those get pushed into the observablecollection. If that fails with result 0x8007048F that means that Bluetooth is disabled on the device, in that case we use the ConnectionSettingsTask to redirect the user to the Bluetooth settings page in WP8.

After the list of peers is build, the user will be able to select one (I’ll discuss the pages in a minute). When a peer is selected we open up the Bluetooth connection

Code Snippet
  1. private async void ConnectToDevice()
  2. {
  3.     if (_socket != null)
  4.     {
  5.         // Disposing the socket with close it and release all resources associated with the socket
  6.         _socket.Dispose();
  7.     }
  8.  
  9.     try
  10.     {
  11.         _socket = new StreamSocket();
  12.  
  13.         //connect to the service with specified GUID
  14.         await _socket.ConnectAsync(SelectedPeer.HostName, "{7A51FDC2-FDDF-4c9b-AFFC-98BCD91BF93B}");
  15.  
  16.         // Connection was successful
  17.         _dataWriter = new DataWriter(_socket.OutputStream);
  18.         _navigationService.NavigateTo("/ConnectedPage.xaml");
  19.     }
  20.     catch (Exception ex)
  21.     {
  22.         MessageBox.Show(ex.Message);
  23.  
  24.         _socket.Dispose();
  25.         _socket = null;
  26.     }
  27. }

The ConnectAsync method takes in the hostname of the peer and the same GUID we used in the WPF application to start the service. Once the connection is made we take the OutputStream and use it to initialize the DataWriter and we navigate to the ConnectedPage.

Let’s have a quick look at the MainPage xaml.

Code Snippet
  1. <phone:LongListSelector ItemsSource="{Binding Peers}">
  2.     <phone:LongListSelector.ItemTemplate>
  3.         <DataTemplate>
  4.             <TextBlock Margin="12, 0, 0, 12"
  5.                        Style="{StaticResource PhoneTextTitle2Style}"
  6.                        Text="{Binding DisplayName}" />
  7.         </DataTemplate>
  8.     </phone:LongListSelector.ItemTemplate>
  9.     <i:Interaction.Behaviors>
  10.         <behaviors:SelectedItemBehavior SelectedItem="{Binding SelectedPeer, Mode=TwoWay}" />
  11.     </i:Interaction.Behaviors>
  12.  
  13. </phone:LongListSelector>

The MainPage consists of a LongListSelector with an ItemsSource bound to the observableCollection on the MainViewModel. as a DataContext we show the displaynames of all available peers.

NOTE: LongListSelector does not support SelectedItem binding. I’ve added a behavior to this project that gives us just that. For more information on the behavior see my blogpost from a while ago.

The ConnectedPage only has a button with a command bound to the GoToStartCommand on MainViewModel. Once that command is fired we send a string “Start” on to the stream.

Code Snippet
  1. private async void SendCommand()
  2. {
  3.     _dataWriter.WriteString("Start");
  4.     await _dataWriter.StoreAsync();
  5.     await _dataWriter.FlushAsync();
  6. }

And that’s it! The message gets written into the DataWriter, stored in the stream and the stream gets flushed. In the WPF app the string gets read into the buffer as a byte array, gets converted back into a string and the Start screen appears!

Wrap-up

In this post I’ve discussed how to connect your Windows Phone device to another bluetooth enabled device and use a service running there.

Happy coding!


Tags:

.Net | Devices | Bluetooth | MVVM Light | WP8 | WPF | XAML | Windows programming

Branching XAML Styler

by Nico

Some time ago I blogged about having recompiled the great XAML Styler plugin so it would install into Visual Studio 2013. The recompiled plugin suddenly became an unexpected success and it got me thinking that this plugin should really continue to exist, even if the original author isn’t supporting it anymore (not sure of this but it has been quite some time since he pushed anything to Codeplex).

After waiting around a bit I’ve decided to download the original source code, get it up and running in Visual Studio 2013 and push it to both Github and the Visual Studio gallery. So I’m happy to announce that the code can be found at Github and the VS2013 version of the plugin can be found at the Visual Studio Gallery

The future?

The version that is now on the gallery is the exact same version that I’ve compiled back in November. It’s the plugin that the original author created but recompiled with the VS2013 SDK. I did create a new VS Package project to be able to have it on the gallery side by side with the original plugin.

As for the future of the project, I’m currently going through the source code, getting to know the application and the code that makes it tick. Afterwards I’m planning on having a look at the logged issues on the original Codeplex site and tackle those.

Issues

Should you run into any issues while using the forked plugin please log an issue on the Github page.

Contributions

So you want to contribute? Great! Fork the Github version and go wild! Create a Pull request when you’re ready and if everything checks out I’ll happily merge your changes into the main branch and give props to every contribution you make.

Let’s keep this plugin alive and make it even better together!


Tags:

.Net | Community | Patterns | Silverlight | WP7 | WP8 | WPF | WinRT | Windows 8 | XAML | github | OSS

LLS SelectedItem binding through a behavior

by Nico

Back in August I blogged about the ExtendedSelector, an extension of the LongListSelector that gave us a bindable SelectedItem property. A bit of a downside of this approach is that it’s basically a new control. Sure it inherits from the classic LLS underneath but it’s still another control in your XAML code.

Well, to fix this I’ve recreated the SelectedItem dependency property  through a behavior.

The behavior

Code Snippet
  1. public class SelectedItemBehavior : Behavior<LongListSelector>
  2. {
  3.     public readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
  4.         "SelectedItem", typeof(object), typeof(SelectedItemBehavior), new PropertyMetadata(default(object)));
  5.  
  6.     public object SelectedItem
  7.     {
  8.         get { return GetValue(SelectedItemProperty); }
  9.         set { SetValue(SelectedItemProperty, value); }
  10.     }
  11.  
  12.     protected override void OnAttached()
  13.     {
  14.         AssociatedObject.SelectionChanged += AssociatedObjectOnSelectionChanged;
  15.  
  16.         base.OnAttached();
  17.     }
  18.  
  19.     protected override void OnDetaching()
  20.     {
  21.         AssociatedObject.SelectionChanged -= AssociatedObjectOnSelectionChanged;
  22.  
  23.         base.OnDetaching();
  24.     }
  25.  
  26.     private void AssociatedObjectOnSelectionChanged(object sender, SelectionChangedEventArgs args)
  27.     {
  28.         SelectedItem = args.AddedItems[0];
  29.     }
  30. }

It’s an easy one really. The behavior inherits from Behavior<LongListSelector> and has one dependency property. When the behavior gets attached to an LLS we attach the event handler to the SelectionChanged event. When detaching we cleanup by detaching the event handler.

When the SelectionChanged event fires we push the selected item into the dependency property.

Usage

Let’s throw together a quick little app to show the usage of the behavior. First the infamous Person class

Code Snippet
  1. public class Person
  2. {
  3.     public string Name { get; set; }
  4.     public int Age { get; set; }
  5. }

Next is the MainViewModel

Code Snippet
  1. public class MainViewModel : INotifyPropertyChanged
  2. {
  3.     private ObservableCollection<Person> _persons;
  4.     private Person _selectedPerson;
  5.  
  6.     public ObservableCollection<Person> Persons
  7.     {
  8.         get { return _persons; }
  9.         set
  10.         {
  11.             if (_persons == value) return;
  12.  
  13.             _persons = value;
  14.  
  15.             OnPropertyChanged();
  16.         }
  17.     }
  18.  
  19.     public Person SelectedPerson
  20.     {
  21.         get { return _selectedPerson; }
  22.         set
  23.         {
  24.             if (_selectedPerson == value) return;
  25.  
  26.             _selectedPerson = value;
  27.  
  28.             OnPropertyChanged();
  29.         }
  30.     }
  31.  
  32.     public MainViewModel()
  33.     {
  34.         Persons = new ObservableCollection<Person>();
  35.         Random rnd = new Random();
  36.  
  37.         for (int i = 0; i < 20; i++)
  38.         {
  39.             var person = new Person {Name = "Person " + i, Age = rnd.Next(0, 80)};
  40.  
  41.             Persons.Add(person);
  42.         }
  43.     }
  44.  
  45.     public event PropertyChangedEventHandler PropertyChanged;
  46.  
  47.     protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  48.     {
  49.         PropertyChangedEventHandler handler = PropertyChanged;
  50.         if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  51.     }
  52. }

Two properties here, an observable collection that holds the persons and a SelectedPerson that will be bound to the dependency property on our behavior. The list of persons gets filled with some random data from the constructor.

Here’s the view

Code Snippet
  1. <Grid x:Name="LayoutRoot" Background="Transparent">
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="Auto" />
  4.         <RowDefinition Height="*" />
  5.     </Grid.RowDefinitions>
  6.  
  7.     <!--  TitlePanel contains the name of the application and page title  -->
  8.     <StackPanel x:Name="TitlePanel"
  9.         Grid.Row="0"
  10.         Margin="12,17,0,28">
  11.         <TextBlock Margin="12,0"
  12.             Style="{StaticResource PhoneTextNormalStyle}"
  13.             Text="MY APPLICATION" />
  14.         <TextBlock Margin="9,-7,0,0"
  15.             Style="{StaticResource PhoneTextTitle1Style}"
  16.             Text="page name" />
  17.     </StackPanel>
  18.  
  19.     <!--  ContentPanel - place additional content here  -->
  20.     <Grid x:Name="ContentPanel"
  21.         Grid.Row="1"
  22.         Margin="12,0,12,0">
  23.  
  24.         <Grid.RowDefinitions>
  25.             <RowDefinition Height="Auto" />
  26.             <RowDefinition Height="*" />
  27.         </Grid.RowDefinitions>
  28.         <TextBlock Grid.Row="0">
  29.             <Run Text="Selected person is " />
  30.             <Run Text="{Binding SelectedPerson.Age}" />
  31.             <Run Text=" years old" />
  32.         </TextBlock>
  33.         <phone:LongListSelector Grid.Row="1"
  34.             ItemsSource="{Binding Persons}">
  35.             <phone:LongListSelector.ItemTemplate>
  36.                 <DataTemplate>
  37.                     <Grid Margin="0, 12, 0, 0">
  38.                         <TextBlock Text="{Binding Name}" />
  39.                     </Grid>
  40.                 </DataTemplate>
  41.             </phone:LongListSelector.ItemTemplate>
  42.             <i:Interaction.Behaviors>
  43.                 <vm:SelectedItemBehavior SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"/>
  44.             </i:Interaction.Behaviors>
  45.         </phone:LongListSelector>
  46.     </Grid>
  47. </Grid>

Let’s extract the LongListSelector from that page as that’s the important piece

Code Snippet
  1. <phone:LongListSelector Grid.Row="1"
  2.     ItemsSource="{Binding Persons}">
  3.     <phone:LongListSelector.ItemTemplate>
  4.         <DataTemplate>
  5.             <Grid Margin="0, 12, 0, 0">
  6.                 <TextBlock Text="{Binding Name}" />
  7.             </Grid>
  8.         </DataTemplate>
  9.     </phone:LongListSelector.ItemTemplate>
  10.     <i:Interaction.Behaviors>
  11.         <vm:SelectedItemBehavior SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"/>
  12.     </i:Interaction.Behaviors>
  13. </phone:LongListSelector>

The ItemsSource is bound to the Persons ObservableCollection on the viewmodel. Underneath the ItemTemplate we attach the behavior and bind its property to the SelectedItem.

And that’s it, every time a person is selected from the LLS the SelectedPerson property gets updated on the viewmodel.


Tags:

.Net | Devices | WP8 | XAML | Binding

First time MVP!

by Nico

The year 2014 started of with a bang for me. On January 1st I was very honored to receive this mail

Meaning I just became a Microsoft MVP in the field of Client Development. I’m joining some big names in that group, names like Gill Cleeren, Laurent Bugnion, Fons Sonnemans, Jesse Liberty and many more (for a complete list, see the MVP site)

The most mind blowing thing for me is that in a few months I’ll be able to go to the MVP summit and talk to these big guys that I’ve been looking up to for years.

Thank you Microsoft for the trust and the honor!


Tags:

Community | MVP

Marker based AR with Monogame and WP8

by Nico

Marker based Augmented Reality is really easy thanks to toolkits like SLAR. A bigger challenge is when you want to use those toolkits in a Monogame application. There’s a lot of information out there on how to do this in the classic Silverlight / XNA mashup we used to have in Windows Phone 7 but since XNA isn’t supported in WP8 and Monogame / Silverlight combinations aren’t possible I embarked on a journey to get this done.

Credits

Before I start with this post I would like to give credits to the three articles / demo apps that helped me create this post.

All of these articles contain code that can be found in my demo solution attached to this post.

Displaying the phone’s camera feed

In a XAML application it’s easy to get the camera feed displayed in the app, a videobrush attached to a Canvas or a Rectangle and done. In a Monogame application we’ll have to do a bit more work.

We’ll start with a blank Monogame Windows Phone 8 game.

Note: the current Monogame templates included in the installer are only suited for Visual Studio 2012. However, once the game’s created you can simply open the solution in Visual Studio 2013.

First thing to do is enable the correct capability. In the WMAppManifest GUI, in the Capabilities tab, check the ID_CAP_ISV_CAMERA checkbox.

From here on out, everything we’ll be doing will be in the Game1.cs class. The GamePage files are just for initializing Monogame and rendering the game. Running the app at this point should just give you a nice blue background.

If the app shows it’s pretty blue background, it’s time to declare some private fields in the Game1 class.

Code Snippet
  1. //camera preview
  2. private PhotoCaptureDevice _photoDevice;
  3. private Texture2D _previewTexture;
  4. private bool _newPreviewFrameAvailable;
  5. private int _backBufferXCenter;
  6. private int _backBufferYCenter;
  7. private int _textureYCenter;
  8. private int _textureXCenter;
  9. private float _yScale;
  10. private float _xScale;
  11. private int[] _previewData2;
  12. private int[] _previewData1;
  13. private bool _isFocussing;

Let’s go over these fields

  • _photoDevice will be our access to the phone’s camera
  • _previewTexture will hold the frame currently being drawn, coming from the camera’s previewbuffer
  • _newPreviewFrameAvailable is a flag that will be set to true whenever a new frame is ready to be fetched and drawn
  • _backBufferXCenter and _backBufferYCenter: these 2 fields together form the middle point of the device’s screen, we need this to position the preview image in the middle of the screen
  • _textureYCenter and _textureXCenter: these 2 fields together form the middle point of the preview image.
  • _yScale and _xScale will contain the height and width scale so that we can draw the preview image full screen
  • _previewData1 and _previewData2 will hold the new and previous pixels from the camera’s preview buffer, we need to hold both to prevent one from being overwritten with a new frame while still being drawn
  • _isFocussing is a flag that prevents the focus function of the camera being called multiple times.

The next step is the Initialize method, note that this method needs to be overridden from the base Game class that Game1 inherits. The method itself gets called automatically at game’s start.

Code Snippet
  1. protected override async void Initialize()
  2. {
  3.     _spriteBatch = new SpriteBatch(GraphicsDevice);
  4.  
  5.     Size previewSize = PhotoCaptureDevice.GetAvailablePreviewResolutions(CameraSensorLocation.Back)[0];
  6.     Size captureSize = PhotoCaptureDevice.GetAvailableCaptureResolutions(CameraSensorLocation.Back)[0];
  7.  
  8.     CreateTexture((int)previewSize.Width, (int)previewSize.Height);
  9.  
  10.     _previewData1 = new int[_previewTexture.Width * _previewTexture.Height];
  11.     _previewData2 = new int[_previewTexture.Width * _previewTexture.Height];
  12.  
  13.     _photoDevice = await PhotoCaptureDevice.OpenAsync(CameraSensorLocation.Back, captureSize);
  14.     _photoDevice.PreviewFrameAvailable += photoDevice_PreviewFrameAvailable;
  15.  
  16.     _backBufferXCenter = GraphicsDevice.Viewport.Width / 2;
  17.     _backBufferYCenter = GraphicsDevice.Viewport.Height / 2;
  18.     _textureXCenter = _previewTexture.Width / 2;
  19.     _textureYCenter = _previewTexture.Height / 2;
  20.     _yScale = (float)GraphicsDevice.Viewport.Width / _previewTexture.Height;
  21.     _xScale = (float)GraphicsDevice.Viewport.Height / _previewTexture.Width;
  22.  
  23.     base.Initialize();
  24. }

First we initialize the spritebatch, this class will be responsible for drawing the 2D textures, meaning in this case, the camera preview.

Next we get the preview size and capture size from the camera in the phone. We create a texture with the CreateTexture method (explained a bit lower) and declare the two arrays that will hold the current and previous frames.

The camera is launched asynchronously on line 13, hooking up the event handler for the PreviewFrameAvailable event on line 14.

Next, the center points for both the device’s screen and the preview texture are calculated, followed by calculating the scale.

Here’s the CreateTexture method

Code Snippet
  1. private void CreateTexture(int textureWidth, int textureHeight)
  2. {
  3.     _previewTexture = new Texture2D(GraphicsDevice, textureWidth, textureHeight);
  4.     Color[] data = new Color[textureWidth * textureHeight];
  5.  
  6.     for (int i = 0; i < textureWidth * textureHeight; i++)
  7.     {
  8.         data[i] = Color.White;
  9.     }
  10.  
  11.     _previewTexture.SetData(data);
  12. }

This method just created a white texture, the size of what we expect the preview frames to be.

Next up is the event handler for the PreviewFrameAvailable event

Code Snippet
  1. void photoDevice_PreviewFrameAvailable(ICameraCaptureDevice sender, object args)
  2. {
  3.     _newPreviewFrameAvailable = true;
  4. }

This sets a flag to true, this flag will be checked in the Draw method to prevent synchronization problems between threads.

Almost time to show something on screen! Here’s the Draw method, note that this is also an overridden method. In Monogame Update and Draw are the game loop, they are called multiple times per second. Update is where you would update the world, check for collisions, … While Draw is where all the graphical drawing logic sits.

Code Snippet
  1. protected override void Draw(GameTime gameTime)
  2. {
  3.     if (_newPreviewFrameAvailable)
  4.     {
  5.         GraphicsDevice.Clear(Color.CornflowerBlue);
  6.  
  7.         // a new frame is available, get it from the previewbuffer
  8.         _photoDevice.GetPreviewBufferArgb(_previewData2);
  9.  
  10.         //camera uses RGB, Texture2D uses BGR, swap color channels
  11.         SwapRedBlueChannel(_previewData2);
  12.  
  13.         var previewDataTemp = _previewData1;
  14.         _previewData1 = _previewData2;
  15.         _previewData2 = previewDataTemp;
  16.  
  17.         //Convert the pixel array to a texture
  18.         _previewTexture.SetData(_previewData1);
  19.         _newPreviewFrameAvailable = false;
  20.     }
  21.  
  22.     //draw the previewframe
  23.     _spriteBatch.Begin();
  24.     _spriteBatch.Draw(_previewTexture, new Vector2(_backBufferXCenter, _backBufferYCenter), null,
  25.         Color.White,
  26.         (float)Math.PI / 2.0f, new Vector2(_textureXCenter, _textureYCenter),
  27.         new Vector2(_xScale, _yScale), SpriteEffects.None, 0.0f);
  28.     _spriteBatch.End();
  29.  
  30.     base.Draw(gameTime);
  31. }

First thing we’ll do is check for the flag that is set in the PreviewFrameAvailable event. If that’s true we fetch the ARGB preview buffer from the device. That buffer is an integer array, we pass in one of our two integer arrays, it will get filled with the buffer’s data. A problem we’re having here is that the camera returns RGB values while Texture2D uses BGR values. SwapRedBlueChannel is a small method that swaps those channels. Feel free to comment that line out and see for yourself what it does, all blue colors will show up red on your phone’s screen and vice versa. This method is detailed a bit lower on this page.

The next part is swapping the current frame with the previous frame, this is done to prevent a frame that is currently drawn on screen to be overwritten by a new one.

The SetData method on Texture2D takes in an array and will use that data to create the texture’s image.

And finally, we clear the flag again to wait for the next available frame. We are now ready to draw the image on screen. The drawing is done using the spritebatch, all drawing should happen between spritebatch.Begin() and spritebatch.End().

The Draw method has several overloads. The overload we’re using here gives us the ability to rotate and scale the texture. We need this as Monogame on Windows Phone currently has no landscape support.

Let’s break down the parameters for the Draw method.

  • _previewTexture: our Texture2D that got filled with the preview frame’s data, this is the texture that will get drawn on screen
  • new Vector2(_backBufferXCenter, _backBufferYCenter): The position where the texture will get drawn. By default Monogame uses the upper left corner of the texture to position it, in this overload of the Draw method we can change that upper left point to something else as you’ll see in a few parameters
  • null: we don’t need a source rectangle here, just pass in null
  • Color.White: Draw this texture in its original colors
  • (float)Math.PI / 2.0f: this is the rotation, it rotates the entire image 90 degrees, moving us from portrait to landscape mode
  • new Vector2(_textureXCenter, _textureYCenter): origin point, this moves the rotation and location point from the upper left corner of the texture to its center
  • new Vector2(_xScale, _yScale): scales the image to be fullscreen
  • SpriteEffects.None: no extra effects needed
  • 0.0f: default depth

With all this in place, run the game and you should see your camera image being drawn full screen inside a game. However, the image is not focusing. An image in focus is pretty important for marker detection I believe. Let’s implement that a screen tap focuses the camera.

Focusing the camera

First we need to enable the tap gesture in the game. In the Game1 constructor add this line.

Code Snippet
  1. TouchPanel.EnabledGestures = GestureType.Tap;

The logic will go in the Update part of our gameloop, once again an overridden method.

Code Snippet
  1. protected override async void Update(GameTime gameTime)
  2. {
  3.     if (_photoDevice == null) return;
  4.  
  5.     //if a touch event is available, focus the camera
  6.     if (TouchPanel.IsGestureAvailable)
  7.     {
  8.         if (TouchPanel.ReadGesture().GestureType == GestureType.Tap && !_isFocussing)
  9.         {
  10.             _isFocussing = true;
  11.             await _photoDevice.FocusAsync();
  12.             _isFocussing = false;
  13.         }
  14.     }
  15.  
  16.     base.Update(gameTime);
  17. }

First we check if our camera is already initialized, we can’t focus something that doesn’t exist yet. If a gesture is available and it is a tap gesture we set the is focusing flag to true to prevent another focus call when one is in progress. The focusing itself is as easy as calling the asynchronously FocusAsync function on the camera. Reset the flag and done. The camera should now focus whenever you tap the screen in the game.

Now that we have our camera in place, it’s time for the fun stuff. The marker detection!

Augmented Reality

As mentioned in the beginning of this article, we’re going to use the SLAR toolkit. The problem is that the current released version of SLAR (released in May 2010) isn’t compatible with our Windows Phone 8 project. Luckily we can just pluck the code from its Codeplex page, recompile it and it just works. I took the lazy way out and just added the SLAR project to my solution. You’ll notice that SLAR depends on another library called Matrix3DEx that has the same compatibility issue, luckily for us that project also lives on Codeplex. Here are the links

My solution currently looks like this

Also make sure to copy the folders Common and CommonData to the folder where your solution lives or the project won’t compile. Don’t forget to add a reference to your game for the SLAR project.

Back to the code, in the Game1 class we’ll need some extra fields

Code Snippet
  1. private GrayBufferMarkerDetector _arDetector;
  2. private bool _isInitialized;
  3. private bool _isDetecting;
  4. private byte[] _buffer;
  5. private DetectionResult _markerResult;

The first field is the detector, there are several kind of detectors in SLAR, we’re using the GrayBuffer one here. We need two flags to show that everything is initialized and if a detection is currently running. Last but not least we need a byte array that will store the frame that we’re currently scanning for markers. The detectionresult will hold the result of every detected marker so that we can use it to position our model.

Next we’ll initialize all the AR related bits, I’ve put this in a separate method that gets called from the existing Initialize method.

Code Snippet
  1. private void InitializeAR()
  2. {
  3.     //  Initialize the Detector
  4.     _arDetector = new GrayBufferMarkerDetector();
  5.  
  6.     // Load the marker pattern. It has 16x16 segments and a width of 80 millimeters
  7.     var marker = Marker.LoadFromResource("data/Marker_SLAR_16x16segments_80width.pat", 16, 16, 80);
  8.  
  9.     // The perspective projection has the near plane at 1 and the far plane at 4000
  10.     _arDetector.Initialize((int)_photoDevice.PreviewResolution.Width, (int)_photoDevice.PreviewResolution.Height, 1, 4000, marker);
  11.  
  12.     _isInitialized = true;
  13. }

The way SLAR works is that it loads in a pattern(*.pat) file. That pattern gets searched for in every detect call. You can create your own patterns or use prebuild ones. I’m using one that comes with the SLAR samples. Make sure that the pattern is included with your solution and that its build action is set to Resource. Line 7 loads the pattern, line 10 initializes our detector, passing in the expected resolution, the near and far planes and the marker.

And now for the magical piece of code that does the actual detecting

Code Snippet
  1. private void Detect()
  2. {
  3.     if (_isDetecting || !_isInitialized)
  4.     {
  5.         return;
  6.     }
  7.  
  8.     //Here is where we try to detect the marker
  9.     _isDetecting = true;
  10.  
  11.     try
  12.     {
  13.         // Update buffer size
  14.         var pixelWidth = _photoDevice.PreviewResolution.Width;
  15.         var pixelHeight = _photoDevice.PreviewResolution.Height;
  16.         if (_buffer == null || _buffer.Length != pixelWidth * pixelHeight)
  17.         {
  18.             _buffer = new byte[System.Convert.ToInt32(pixelWidth * pixelHeight)];
  19.         }
  20.  
  21.         // Grab snapshot for the marker detection
  22.         _photoDevice.GetPreviewBufferY(_buffer);
  23.  
  24.         //Detect the markers
  25.         _arDetector.Threshold = 100;
  26.         var dr = _arDetector.DetectAllMarkers(_buffer, System.Convert.ToInt32(pixelWidth), System.Convert.ToInt32(pixelHeight));
  27.  
  28.         //Set the marker result if the marker is found
  29.         _markerResult = dr.HasResults ? dr[0] : null;
  30.     }
  31.     finally
  32.     {
  33.         _isDetecting = false;
  34.     }
  35. }

The Detect method will get called from a timer, more on that a bit lower in the article.

First we’ll check if it’s okay to do detection, a detection cannot be in progress and everything should be initialized. Then we’ll set the is detecting flag to true.

We’ll keep the width and height of the camera’s preview resolution in two variables and initialize the buffer if necessary. We fill the buffer with the luminance data from the camera by calling the GetPreviewBufferY method, this differs from the method we’re using to show the camera stream. The luminance data is sufficient for SLAR to do its detection. Then we pass in the buffer to the marker detector, together with the frame’s width and height. If a result is found we’ll keep it in the DetectionResult field, if not we set the field to null. As last part we clear the is detecting flag so we are ready to detect again.

Very easy to use, SLAR takes care of all the rest. All we need to do is call the Detect method. In the overridden Initialize method, add this.

Code Snippet
  1. InitializeAR();
  2.  
  3. //marker detection sits on another counter than the update / draw mechanism to prevent excessive detection
  4. Deployment.Current.Dispatcher.BeginInvoke(() =>
  5. {
  6.     //Runt the detection separate from the update
  7.     var dispatcherTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) };
  8.     dispatcherTimer.Tick += (sender, e1) => Detect();
  9.     dispatcherTimer.Start();
  10. });

The detection runs separately from the gameloop to prevent excessive calls to the detect method. I only want to detect every 100 milliseconds.

When you run the game now and point the camera to the marker, nothing happens. That’s perfectly normal. The marker is getting detected but we’re not doing anything with the detection results yet. Let’s add a 3D model to our game and position it on the marker.

Adding the model

For the 3D model I choose a model of the Tardis I found online (if you don’t know what the Tardis is, go out and buy all the Doctor Who dvd boxes you can find and lock yourself in your room for a few months. Thank me afterwards).

To use this in Monogame you’ll need to push it through either the XNA or the Monogame pipeline to convert it into an XNB file. I’m not going to detail how to do this here, lots of info out there. If you want a quick start, grab the XNB file from my demo project.

Add a folder called Content to your solution, add the XNB file in there and set its build action to Content. Next, we’ll once again add some fields to the Game1 class.

Code Snippet
  1. private Vector3 _modelPosition;
  2. private Vector3 _cameraPosition;
  3. private Model _tardis;
  4. private float _aspectRatio;

The names speak for themselves, we’ve got two vectors, one for the position of the Tardis, one for the position of the camera. We’ve got the Tardis model and a field that holds the aspect ratio.

In the Initialize method, right before the call to InitializeAR add these lines.

Code Snippet
  1. _aspectRatio = _graphics.GraphicsDevice.Viewport.AspectRatio;
  2. _modelPosition = Vector3.Zero;
  3. _cameraPosition = new Vector3(0, 0, 50);
  4.  
  5. InitializeAR();

These are just basic vectors that we’ll use to calculate the actual position on screen where we need to render our model.

Next, we’ll need to load the model into memory. This is done in the overridden LoadContent method in the Game1 class.

Code Snippet
  1. protected override void LoadContent()
  2. {
  3.     _tardis = Content.Load<Model>("tardis");
  4.  
  5.     base.LoadContent();
  6. }

There’s no need to specify that the model lives in the Content folder as Monogame assumes that the project contains a folder called Content and that’s where it looks for XNB files.

Before we go into the draw logic of the model, there’s one problem that we’ll need to tackle. SLAR is using Matrix3D classes while Monogame has its own Matrix class. We’ll need a way to convert Matrix3D to Matrix. Here’s an extension method that does just that.

Code Snippet
  1. public static class MatrixConverter
  2. {
  3.     /// <summary>
  4.     /// Convert a Silverlight matrix into an Xna matrix
  5.     /// </summary>
  6.     /// <param name="matrix"></param>
  7.     /// <returns></returns>
  8.     public static Matrix ToXnaMatrix(this System.Windows.Media.Media3D.Matrix3D matrix)
  9.     {
  10.         var m = new Matrix(
  11.            (float)matrix.M11, (float)matrix.M12, (float)matrix.M13, (float)matrix.M14,
  12.            (float)matrix.M21, (float)matrix.M22, (float)matrix.M23, (float)matrix.M24,
  13.            (float)matrix.M31, (float)matrix.M32, (float)matrix.M33, (float)matrix.M34,
  14.            (float)matrix.OffsetX, (float)matrix.OffsetY, (float)matrix.OffsetZ, (float)matrix.M44);
  15.  
  16.         return m;
  17.     }
  18. }

Now, onto the Draw method. The position of the following code is really important. Monogame draws its stuff in the order that you feed it its instructions. Meaning that we first need to draw the camera feed, then the Tardis model. That way the model will be nicely overlaid over the image.

In the Draw method, after Spritebatch.End and before base.Draw add these lines

Code Snippet
  1. if (_markerResult != null)
  2. {
  3.     //a marker is detected, draw the Tardis model
  4.     var result = _markerResult;
  5.     _graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
  6.     _graphics.GraphicsDevice.BlendState = BlendState.Opaque;
  7.     _graphics.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
  8.  
  9.     // Copy any parent transforms.
  10.     Matrix[] transforms = new Matrix[_tardis.Bones.Count];
  11.     _tardis.CopyAbsoluteBoneTransformsTo(transforms);
  12.  
  13.     // Draw the model. A model can have multiple meshes, so loop.
  14.     foreach (ModelMesh mesh in _tardis.Meshes)
  15.     {
  16.         // This is where the mesh orientation is set, as well as our camera and projection.
  17.         foreach (BasicEffect effect in mesh.Effects)
  18.         {
  19.             effect.EnableDefaultLighting();
  20.             effect.World = Matrix.CreateScale(0.1f) *
  21.                            (transforms[mesh.ParentBone.Index] * mesh.ParentBone.Transform *
  22.                             Matrix.CreateTranslation(_modelPosition) *
  23.                             result.Transformation.ToXnaMatrix());
  24.  
  25.             effect.View = Matrix.CreateLookAt(_cameraPosition, Vector3.Zero, Vector3.Up);
  26.             effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
  27.                 _aspectRatio, 1.0f, 10000f);
  28.         }
  29.  
  30.         // Draw the mesh, using the effects set above.
  31.         mesh.Draw();
  32.     }
  33. }

Since we’re using a 3D model we can’t use the spritebatch to draw it. We set some properties onto the graphicsdevice first. Then we grab all transforms that are included in the model. The Tardis model I’m using is very simple, it’s just a box, so no transformations there.

We loop through all the meshes in the model, for each mesh we loop through its effects and that’s where we set the position. We use the detection result his transformation matrix to calculate the world for each effect and we draw each mesh.

Here’s the result:

Conclusion

The end result might not seem like much, but that’s because my 3D monogame skills are very lacking Glimlach but just consider what we’ve done here. We’ve added a camera stream into a game, we’ve used that same stream to detect a certain pattern and we’ve positioned a game element onto that pattern. From here I’ll leave the rest to your imagination.

The project can be downloaded from my Skydrive.


Tags:

Augmented Reality | .Net | MonoGame | Devices | WP8 | XNA

Data validation in Windows Phone 8

by Nico

Whenever you need to do data input you’re probably going to add some form of data validation. There is a ton of information out there on how to do this in Silverlight and WPF but information on Windows Phone 8 is rather hard to find. After doing some research on the topic I’ve landed on the Fluent Validation library available on Nuget and decided to write something on the subject myself. I’ve put together a quick sample, including integration with SimpleIoc in MVVM Light.

Adding the package

We start of with an empty solution, add the MVVM Light libraries to it, bind the datacontext of MainPage to MainViewModel as you would usually do. Once the MVVM setup is complete it’s time to add the Fluent Validation package to the project.

Install-Package FluentValidation

Fluent Validation is an open source project available on Codeplex

Fluent Validation has libraries for

  • .net 4.0
  • MVC 3
  • MVC 4
  • MVC 5
  • Portable

The settings of the portable class library are

Meaning that the implementation I’m about to show will work just as well on Windows Store apps, so +1 for code sharing!

Creating the Model

The demo app is a simple registration form, a new user will be able to enter his name, birthdate and country. We’ll build validation rules on those properties later on. We’ll only have one model class in this app, called Member.

Code Snippet
  1. public class Member
  2. {
  3.     public string Name { get; set; }
  4.     public DateTime BirthDate { get; set; }
  5.     public string Country { get; set; }
  6. }

Setting up the validation

There is some work involved in getting everything setup, don’t worry, it’s hardly rocket science.

We’re going to create a ValidaterFactory. We need this because we’re going to use SimpleIoc to inject the validators into the ViewModels. If you don’t want to do this you can just create the validators and instantiate them whenever you need one, the Codeplex page of Fluent Validation has great documentation on this.

A ValidatorFactory inherits from the ValidatorFactoryBase class included in the library

Code Snippet
  1. public class ValidatorFactory : ValidatorFactoryBase
  2. {
  3.     public ValidatorFactory()
  4.     {
  5.         //register the Validators
  6.         SimpleIoc.Default.Register<IValidator<Member>, MemberValidator>();
  7.     }
  8.  
  9.     public override IValidator CreateInstance(Type validatorType)
  10.     {
  11.         return SimpleIoc.Default.GetInstance(validatorType) as IValidator;
  12.     }
  13. }

The constructor of the ValidatorFactory is where I’m registering all validators. You could do this in the ViewModelLocator as well, like any other class / repository / viewmodel but this keeps my VMLocator cleaner and keeps the validation logic a bit closer together.

The CreateInstance function needs to be overridden and returns the instance of the requested validator.

Building a validator

Almost there, in this step we’re building a validator for the Member class. A validator inherits from AbstractValidator<T> where T is the class you want to validate.

Code Snippet
  1. public class MemberValidator : AbstractValidator<Member>
  2. {
  3.     public MemberValidator()
  4.     {
  5.         RuleFor(member => member.Name).NotEmpty();
  6.         RuleFor(member => member.BirthDate).LessThan(DateTime.Today);
  7.     }
  8. }

In the constructor of the validator we can finally start to add some rules. In this case we’re saying that the Name property should not be empty and that the birthdate property should be before today’s date.

We’ll need to register this class into our IOC, so in ViewModelLocator add this line

Code Snippet
  1. SimpleIoc.Default.Register<ValidatorFactory>(true);

We pass in ‘true’ as parameter to make sure the object is instantiated at the moment of registration, that way all validators are registered in the IOC as well (as seen in the ValidatorFactory’s constructor).

As a reference, these are all the built in validators of Fluent Validation

  • NotNull
  • NotEmpty
  • NotEqual
  • Equal
  • Length
  • LessThan
  • LessThanOrEqual
  • GreaterThan
  • GreaterThanOrEqual
  • Predicate
  • RegEx
  • Email

Quite an impressive list, and probably most of what you’ll need. Just in case that the one that you need isn’t included, you can build your own, we’ll discuss that in a bit. Let’s get these rules to work first.

Validating data

So we have a factory, we have a validator, all are getting registered in our IOC, time to hook up the ViewModels and getting some validation done.

In the MainViewModel we add a property of type Member that we’ll bind against

Code Snippet
  1. private Member _newMember;
  2. public Member NewMember
  3. {
  4.     get { return _newMember; }
  5.     set
  6.     {
  7.         if (_newMember == value) return;
  8.  
  9.         _newMember = value;
  10.  
  11.         RaisePropertyChanged(() => NewMember);
  12.     }
  13. }

Next, we’ll add two fields, one for the validator and one for the save command

Code Snippet
  1. private ICommand _saveMemberCommand;
  2. private IValidator<Member> _validator;

Next up is the ICommand property for the Save Command

Code Snippet
  1. public ICommand SaveMemberCommand
  2. {
  3.     get { return _saveMemberCommand ?? (_saveMemberCommand = new RelayCommand(SaveMember)); }
  4. }

Before we dive into the SaveMember method, we’ll need to do some constructor injection and initialization.

Code Snippet
  1. public MainViewModel(ValidatorFactory validator)
  2. {
  3.     NewMember = new Member
  4.     {
  5.         BirthDate = DateTime.Today
  6.     };
  7.  
  8.     _validator = validator.GetValidator<Member>();
  9. }

As a parameter we get our ValidatorFactory, using its GetValidator<T> function we can fill up the _validator field. NewMember gets instantiated and the BirthDate property is set to a default of today.

And last but not least, the SaveMember method

Code Snippet
  1. private void SaveMember()
  2. {
  3.     if (IsValid())
  4.     {
  5.         MessageBox.Show("Registration completed!");
  6.     }
  7. }
  8.  
  9. private bool IsValid()
  10. {
  11.     ValidationResult validationResult = _validator.Validate(NewMember);
  12.  
  13.     if (!validationResult.IsValid)
  14.     {
  15.         ShowErrors(validationResult.Errors);
  16.  
  17.         return false;
  18.     }
  19.  
  20.     return true;
  21. }
  22.  
  23. private void ShowErrors(IEnumerable<ValidationFailure> errors)
  24. {
  25.     StringBuilder builder = new StringBuilder();
  26.  
  27.     builder.AppendLine("The following errors occured:");
  28.     foreach (ValidationFailure error in errors)
  29.     {
  30.         builder.AppendLine("- " + error.ErrorMessage);
  31.     }
  32.  
  33.     MessageBox.Show(builder.ToString(), "error", MessageBoxButton.OK);
  34. }

To validate an instance we call the Validate function on a validator for that type, in this case ‘Member’. That function returns a ValidationResult. ValidationResult contains a bool property IsValid and a list of errors that it found.

We iterate over this list and put every error into a StringBuilder to get a nice error message in a messagebox. If I try to save with an empty name and today’s date as birthdate I get this.

Our validation is working! But those messages could be a bit better. Fluent Validator provides us with options to adjust the property name or the entire message. Change the constructor of the MemberValidator to this

Code Snippet
  1. public MemberValidator()
  2. {
  3.     RuleFor(member => member.Name).NotEmpty().WithMessage("You should enter your name");
  4.     RuleFor(member => member.BirthDate).LessThan(DateTime.Today).WithName("date of birth");
  5. }

On line 3 we use .WithMessage(“”) to replace the default message by whatever we want. Line 4 replaces the default name of the property, the result is similar yet slightly different

Adding a custom validator

Let’s say that we want to add validation to the Country property. This property must have a value of either ‘Belgium’, ‘Netherlands’ or ‘Luxemburg’ (this is called the BeNeLux). Obviously, this isn’t included as one simple validator so we’ll just build it ourselves.

We’ll need a class that inherits from PropertyValidator and overrides the IsValid function.

Code Snippet
  1. public class CountryMustBeInBenelux : PropertyValidator
  2. {
  3.     public CountryMustBeInBenelux()
  4.         : base("{PropertyName} is not a Benelux country")
  5.     {
  6.  
  7.     }
  8.  
  9.     protected override bool IsValid(PropertyValidatorContext context)
  10.     {
  11.         if (context.PropertyValue == null)
  12.             return false;
  13.  
  14.         string country = context.PropertyValue.ToString().ToLower();
  15.  
  16.         return country == "belgium" || country == "netherlands" || country == "luxemburg";
  17.     }
  18. }

The string that we pass in to the base constructor is the default message that will be used for this validator. The IsValid function takes a parameter of PropertyValidatorContext. This will contain the property that we want to validate and its value.

Next, in the MemberValidator constructor we add the validation for the Country property

Code Snippet
  1. public MemberValidator()
  2. {
  3.     RuleFor(member => member.Name).NotEmpty().WithMessage("You should enter your name");
  4.     RuleFor(member => member.BirthDate).LessThan(DateTime.Today).WithName("date of birth");
  5.  
  6.     RuleFor(member => member.Country).SetValidator(new CountryMustBeInBenelux());
  7. }

As you can see we need to use the SetValidator function to add our own validator.

The result now is this (I’ve entered a name and a valid birthdate to clean up the error list a bit)

 

Conclusion

In this article I’ve discussed the use of Fluent Validator to do data validation in Windows Phone 8 apps. I’ve used the portable version of the library so these examples should work just fine on Windows 8 as well.

The Fluent Validator library has many more options than what I’ve discussed here and they are all well documented, head over the the Codeplex page if you want to do more and deeper validation.

The sample project can be found on my SkyDrive


Tags:

.Net | Data | Validation | Fluent | MVVM Light | NuGet | WP8 | Windows 8 | WinRT | XAML

Xaml Styler for Visual Studio 2013

by Nico

Xaml Styler is a free Visual Studio 2012 extension available from the gallery. I’ve been using this extension for quite some time now and I’m really happy with how it styles my XAML code. Unfortunately the extension isn’t compatible with Visual Studio 2013.

Luckily for us, the extension is on Codeplex. I’ve downloaded the code, referenced the new Visual Studio SDK and recompiled it. It seems to be working fine with Visual Studio 2013 now.

I’ve uploaded the binaries to my Skydrive folder so that everyone can enjoy the extension in Visual Studio 2013 until the original author of the plug-in creates official Visual Studio 2013 support.

Be aware, this version isn’t thoroughly tested by anyone! I’ve compiled it, installed it and I’m currently using it. I haven’t ran into any problems yet but that doesn’t mean that it won’t have any problems. These binaries are supplied as-is.

Download from Skydrive

Gallery link

Original Codeplex page


Tags:

.Net | WP7 | WP8 | WPF | WinRT | Windows 8 | XAML

ViewModelBackstack for when you navigate to the same page

by Nico

When working on my comic application for Windows Phone I encountered a problem that I’ve had in the past and have heard others ran into as well. When on the detailspage of a comic character I have a list of enemies of that character. Those enemies are clickable to load their details. Nothing hard there, but both the first character and its enemies are of the same type and they use the same view and viewmodel to show their data. This isn’t hard to do, the difficult part is using the phone’s back button. After navigating to the same CharacterDetailPage 4 times I would expect the back button to take me back through all the characters I’ve viewed.

I was trying to use OnNavigatedTo and OnNavigatedFrom events but apparently those do not fire when navigating to the same page. After a bit of tinkering I came up with a ViewModelBackstack class that does the trick.

I’ve uploaded the class and a sample project to GitHub and I’ve created a NuGet package for everyone to use (my very first public package, hooray!). In this post I’ll walk through the sample project to explain how it works.

First of all, if you want to add the package to your solution, search for ViewModelBackstack on NuGet or use the command line

Install-Package ViewModelBackstack

Once that’s setup start building your application, MVVM style (the sample application uses MVVM Light, but ViewModelBackstack should work with all the other ones out there).

The sample application

The sample application is a basic one, it has two pages, a MainPage and a GuidPage. The MainPage only contains some text and a button to navigate to the second page. The GuidPage contains a textblock that is bound to a property on the viewmodel, and a button that simulates navigating to the same page again but loading in different data.

The scenario is this:

MainPage > GuidPage > GuidPage > GuidPage > …

MainVM > GuidVM > GuidVM > GuidVM > …

Follow it the other way around to know how the back button will respond.

The ViewModelBackstack class

ViewModelBackstack is a static class, and not a very big one.

Code Snippet
  1. public static class ViewModelBackStack
  2. {
  3.     private static Dictionary<string, string> _viewModelStack;
  4.  
  5.     public static void Add(string key, object value)
  6.     {
  7.         if (_viewModelStack == null)
  8.             _viewModelStack = new Dictionary<string, string>();
  9.  
  10.         _viewModelStack.Add(key, JsonConvert.SerializeObject(value));
  11.     }
  12.  
  13.     public static object Take<T>(string key)
  14.     {
  15.         string toReturn = _viewModelStack[key];
  16.         Delete(key);
  17.  
  18.         return JsonConvert.DeserializeObject<T>(toReturn);
  19.     }
  20.  
  21.     public static bool TryTake<T>(string key, out T value)
  22.         where T : class
  23.     {
  24.         try
  25.         {
  26.             value = JsonConvert.DeserializeObject<T>(_viewModelStack[key]);
  27.             Delete(key);
  28.  
  29.             return true;
  30.         }
  31.         catch (Exception)
  32.         {
  33.             value = null;
  34.             return false;
  35.         }
  36.     }
  37.  
  38.     public static bool ContainsKey(string key)
  39.     {
  40.         if (_viewModelStack == null)
  41.             return false;
  42.  
  43.         return _viewModelStack.ContainsKey(key);
  44.     }
  45.  
  46.     public static void Delete(string key)
  47.     {
  48.         _viewModelStack.Remove(key);
  49.     }
  50.  
  51.     public static void Replace(string key, object newValue)
  52.     {
  53.         _viewModelStack[key] = JsonConvert.SerializeObject(newValue);
  54.     }
  55.  
  56.     public static bool CanGoBack()
  57.     {
  58.         if (_viewModelStack == null)
  59.             return false;
  60.  
  61.         return _viewModelStack.Count > 0;
  62.     }
  63.  
  64.     public static T GoBack<T>()
  65.     {
  66.         var toReturn = _viewModelStack.Last();
  67.         _viewModelStack.Remove(toReturn.Key);
  68.  
  69.         return JsonConvert.DeserializeObject<T>(toReturn.Value);
  70.     }
  71. }

It contains a Dictionary<string, string> that will hold the instances of the viewmodels. The instances are serialized into JSON strings with Json.net. This to save memory and avoid reference issues.

There are some methods in there to manually take out a specific instance or to delete one. But more importantly are the CanGoBack() and GoBack() methods. Let’s have a look at how to use this.

Usage

In the GuidViewModel’s constructor we start listening for a message, when that message arrives we load in new data (in this case, generate a new GUID) GuidString is a normal property that calls RaisePropertyChanged from the setter.

Code Snippet
  1. public GuidViewModel()
  2. {
  3.     Messenger.Default.Register<GenerateNewGuidMessage>(this, msg => GenerateGuid());
  4. }
  5.  
  6. private void GenerateGuid()
  7. {
  8.     GuidString = Guid.NewGuid().ToString();
  9. }

Next is the command that is bound to the button on the page, this is a RelayCommand that will call the LoadNewData method

Code Snippet
  1. private void LoadNewData()
  2. {
  3.     if (ViewModelBackStack.ContainsKey(GuidString))
  4.         ViewModelBackStack.Replace(GuidString, this);
  5.     else
  6.         ViewModelBackStack.Add(GuidString, this);
  7.  
  8.     Messenger.Default.Send(new GenerateNewGuidMessage());
  9. }

The LoadNewData method will check if the ViewModelBackStack already contains the key we use (each instance needs a unique key, we’re using the GUID in this case). If it’s already there, replace it, if not add it to the backstack. After that, send the message to generate new data.

Note that we’re not actually navigating away from the page, since the NavigationService doesn’t actually navigate when you try going to the same page there’s really no use in trying.

The final step is intercepting the back button press and using it load in a previous instance of the GuidViewModel. We need to do this in the code-behind of the page, since we need to cancel the navigation there (by default, when pressing the back button here it would just take us back to MainPage, so navigation needs to be cancelled).

Code Snippet
  1. protected override void OnBackKeyPress(CancelEventArgs e)
  2. {
  3.     if (ViewModelBackStack.CanGoBack())
  4.     {
  5.         DataContext = ViewModelBackStack.GoBack<GuidViewModel>();
  6.         e.Cancel = true;
  7.         return;
  8.     }
  9.  
  10.     base.OnBackKeyPress(e);
  11. }

OnBackKeyPress can be overriden from PhoneApplicationPage base class. If the ViewModelBackStack can go back we take out the most recent record in the dictionary, deserialize it to T, set that result as datacontext and we’re done. We can cancel the navigation by setting e.Cancel to true. Once the ViewModelBackStack is empty the app will return to MainPage.

Wrap up

So that’s about it. I’m currently building a Windows Phone app that uses the ViewModelBackStack, so there could be some changes coming in the next few weeks, or it might just prove to work perfectly as-is.

Feel free to fork the repo on GitHub and send pull requests if you can enhance / improve upon the project, props will be given Glimlach.


Tags:

.Net | Devices | MVVM Light | NuGet | PCL | WP7 | WP8

  Log in

About the author

Hi,

My name is Nico, I’m an MVP Client Development living in Belgium.
I’m currently employed as a .NET consultant at RealDolmen, one of Belgium’s leading IT single source providers.

I'm also founding member and board member of the Belgian Metro App Developer Network, a user group focussed on Windows 8 and Windows Phone development. If you're in Belgium feel free to drop by if we're doing an event. http://www.madn.be

Since June 2012 I'm a proud member of Microsoft's Extended Experts Team Belgium. And in February 2013 I became a member of DZone's Most Valuable Bloggers family.

In 2013 I became a book author and wrote "Windows 8 app projects, XAML & C# edition".

In 2014 I received the MVP award for the very first time.

I hope to get feedback from my readers either through comments, mail (nico_vermeir@hotmail.com), twitter, facebook, …

 

mvp

 

 

MeetLogo

 

MVBLogo

mybook

 

Month List