Nico's digital footprint

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

SQLite with a bit of MVVM Light in Windows Phone 8

by Nico

While SQLce is still a viable solution in Windows Phone 8 to have some form of local database we also have an official SQLite implementation available. So why use SQLite when we can just keep using SQLce? Because Windows 8 only support SQLite and if you ever want to port over your app it would be nice not to have two versions of local databases to maintain. In this post I’ll explain how to implement a SQLite database into an MVVM Light Windows Phone 8 project (there is an unofficial Windows Phone 7 SQLite version as well but I have no idea how stable / buggy that is). I’ll be using Tim Heuer’s SQLite .net wrapper so we can use LINQ to SQLite instead of writing SQL queries manually (hooray for intellisense Smile). Let’s kick things off by creating an empty Windows Phone 8 app.

SQLite

Before we can use SQLite, we’ll need to install the SDK. Click here (official SQLite download page) to download the VSIX file and install it into Visual Studio.

NuGet fun

Before we can write any code we’ll need some NuGet packages. Use these commands in the Package Manager Console.

Install-Package MvvmLight

Install-Package sqlite-net

Install-Package WPtoolkit

Install-Package Cimbalino.Phone.Toolkit

Changing target platform

SQLite is a C++ library, meaning that it should be compiled against the architecture that the app will be running on. On Windows 8 that means creating separate packages for ARM and x86. On Windows Phone 8 that means switching from Any CPU to ARM when running on a device or when creating your XAP. When you’re running your app on the emulator the target platform needs to be set to x86.

Moving files around

When you  install the MVVM Light package it will add some folder structure and some files. I like to adjust this a bit more by adding a View folder and moving the MainPage into that view. That means that the startup page has to change as well. Open up the WMAppManifest.xml and change it like on the screenshot.

At this stage I couldn’t build the project because of a whole bunch of compile errors in the sqlite-net files. If you get the same problem (by the time you read this, it might be fixed), download the sqlite-net source from GitHub and from your project, add a reference to your local sqlite-net repo/lib/wp7/Community.CsharpSqlite.WinPhone.dll and that should fix it right up. Also, add a folder “Model” to the project so that our MVVM folder structure is complete.

The demo app

The app that we’ll be creating today is an app to keep track of tasks, which seems to be the new “Hello, World!”. We’ll start with the model, and work our way up to the view from there. Our class is called “Task” that means we’ll have to be careful that we use Model.Task instead of System.Threading.Task but we’ll manage.

Code Snippet
  1. [Table("Tasks")]
  2. public class Task : INotifyPropertyChanged
  3. {
  4.     private int _id;
  5.     private string _title;
  6.     private DateTime _date;
  7.  
  8.     [PrimaryKey, AutoIncrement]
  9.     public int Id
  10.     {
  11.         get { return _id; }
  12.         set
  13.         {
  14.             if (value == _id) return;
  15.             _id = value;
  16.             OnPropertyChanged("Id");
  17.         }
  18.     }
  19.  
  20.     public string Title
  21.     {
  22.         get { return _title; }
  23.         set
  24.         {
  25.             if (value == _title) return;
  26.             _title = value;
  27.             OnPropertyChanged("Title");
  28.         }
  29.     }
  30.  
  31.     public DateTime Date
  32.     {
  33.         get { return _date; }
  34.         set
  35.         {
  36.             if (value.Equals(_date)) return;
  37.             _date = value;
  38.             OnPropertyChanged("Date");
  39.         }
  40.     }
  41.  
  42.     public event PropertyChangedEventHandler PropertyChanged;
  43.     protected virtual void OnPropertyChanged(string propertyName = null)
  44.     {
  45.         PropertyChangedEventHandler handler = PropertyChanged;
  46.         if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  47.     }
  48. }

The “Task” class implements INotifyPropertyChanged so that controls that are bound to its properties get updated like good citizens. Now for the annotations, those come from sqlite-net and mark this class as a table in the database. The same goes for the annotations on the Id property, that property is marked as being the primarykey and being an autoincremented value. If you have a property that you don’t want in the database, add the [Ignore] attribute and there won’t be any column generated for it. Now that we have a model we can start working on the service, the class that will do all the SQLite communication. (Yes we could do all this in the viewmodel but it’s called seperation of concerns Smile). And to do this the right way we’ll start by creating an interface for the service.

Code Snippet
  1. public interface IDataService
  2. {
  3.     Task SaveTask(Model.Task newTask);
  4.     Task<IList<Model.Task>> LoadTasks();
  5.     Task UpdateTask(Model.Task selectedTask);
  6.     Task DeleteTask(Model.Task selectedTask);
  7. }

Those are all the basic CRUD (Create, Read, Update, Delete) that we can (should be able to) perform on any datacontainer. Here’s the implementation

Code Snippet
  1. public class DataService : IDataService
  2. {
  3.     public async Task SaveTask(Model.Task newTask)
  4.     {
  5.         await App.Connection.InsertAsync(newTask);
  6.     }
  7.  
  8.     public async Task<IList<Model.Task>> LoadTasks()
  9.     {
  10.         return await App.Connection.Table<Model.Task>().ToListAsync();
  11.     }
  12.  
  13.     public async Task UpdateTask(Model.Task selectedTask)
  14.     {
  15.         await App.Connection.UpdateAsync(selectedTask);
  16.     }
  17.  
  18.     public async Task DeleteTask(Model.Task selectedTask)
  19.     {
  20.         await App.Connection.DeleteAsync(selectedTask);
  21.     }
  22.  
  23.     public async Task<IList<SubTask>> LoadSubTasks()
  24.     {
  25.         return await App.Connection.Table<SubTask>().ToListAsync();
  26.     }
  27. }

Hmm looks like I forgot to mention something, go to App.xaml.cs and add this property

Code Snippet
  1. public static SQLiteAsyncConnection Connection { get; set; }

Keep App.xaml.cs open, we’ll need it in a minute. In the DataService class we’re calling all the CRUD methods provided to us by sqlite-net. We can get a list of all records in a table by calling .Table<T>().ToListAsync() or do any of the other CRUD operations by just calling the function and passing in the modified POCO. Really easy and quite powerful.

Let’s jump back to App.xaml.cs, there should be an empty function called Application_Launching. In this function we’ll need to check if the database exists, open a connection to it if it exists or create it first and then open the connection.

Code Snippet
  1. private async void Application_Launching(object sender, LaunchingEventArgs e)
  2. {
  3.     try
  4.     {
  5.         await ApplicationData.Current.LocalFolder.GetFileAsync("taskDB.db");
  6.         Connection = new SQLiteAsyncConnection("taskDB.db");
  7.     }
  8.     catch (FileNotFoundException)
  9.     {
  10.         CreateDB();
  11.     }
  12. }

Unfortunately, there is no DataBaseExists() function like in SQLce so I choose to do it the quick and dirty way. I try to get the database, which is basically a file in the ApplicationData, if the file doesn’t exist it will throw a FileNotFoundException and that’s where I call the CreateDB() method.

Code Snippet
  1. private async void CreateDB()
  2. {
  3.     Connection = new SQLiteAsyncConnection("taskDB.db");
  4.  
  5.     await Connection.CreateTableAsync<Task>();
  6. }

Line 3 creates the database while line 5 creates the Task table in the database. When all that’s in place, we’re ready to move to the viewmodels.

ViewModel

Not much to say here, we all know what a viewmodel is, so here is the MainViewModel.

Code Snippet
  1. public class MainViewModel : ViewModelBase
  2. {
  3.     private readonly IDataService _dataService;
  4.     private readonly INavigationService _navigationService;
  5.  
  6.     /// <summary>
  7.     /// The <see cref="Tasks" /> property's name.
  8.     /// </summary>
  9.     public const string TasksPropertyName = "Tasks";
  10.  
  11.     private IList<Task> _tasks;
  12.  
  13.     /// <summary>
  14.     /// Sets and gets the Tasks property.
  15.     /// Changes to that property's value raise the PropertyChanged event.
  16.     /// </summary>
  17.     public IList<Task> Tasks
  18.     {
  19.         get
  20.         {
  21.             return _tasks;
  22.         }
  23.  
  24.         set
  25.         {
  26.             if (Equals(_tasks, value))
  27.             {
  28.                 return;
  29.             }
  30.  
  31.             RaisePropertyChanging(TasksPropertyName);
  32.             _tasks = value;
  33.             RaisePropertyChanged(TasksPropertyName);
  34.         }
  35.     }
  36.        
  37.     /// <summary>
  38.     /// The <see cref="NewTask" /> property's name.
  39.     /// </summary>
  40.     public const string NewTaskPropertyName = "NewTask";
  41.  
  42.     private Task _newTask;
  43.  
  44.     /// <summary>
  45.     /// Sets and gets the NewTask property.
  46.     /// Changes to that property's value raise the PropertyChanged event.
  47.     /// </summary>
  48.     public Task NewTask
  49.     {
  50.         get
  51.         {
  52.             return _newTask;
  53.         }
  54.  
  55.         set
  56.         {
  57.             if (_newTask == value)
  58.             {
  59.                 return;
  60.             }
  61.  
  62.             RaisePropertyChanging(NewTaskPropertyName);
  63.             _newTask = value;
  64.             RaisePropertyChanged(NewTaskPropertyName);
  65.         }
  66.     }
  67.  
  68.     public RelayCommand SaveNewTaskCommand
  69.     {
  70.         get { return new RelayCommand(SaveNewTask); }
  71.     }
  72.  
  73.     public RelayCommand<SelectionChangedEventArgs> SelectionChangedCommand
  74.     {
  75.         get { return new RelayCommand<SelectionChangedEventArgs>(SelectionChanged);}
  76.     }
  77.  
  78.     /// <summary>
  79.     /// Initializes a new instance of the MainViewModel class.
  80.     /// </summary>
  81.     public MainViewModel(IDataService dataService, INavigationService navigationService)
  82.     {
  83.         _dataService = dataService;
  84.         _navigationService = navigationService;
  85.         NewTask = new Task { Date = DateTime.Today };
  86.  
  87.         LoadTasks();
  88.     }
  89.  
  90.     private async void LoadTasks()
  91.     {
  92.         Tasks = await _dataService.LoadTasks();
  93.     }
  94.  
  95.     private async void SaveNewTask()
  96.     {
  97.         await _dataService.SaveTask(NewTask);
  98.         Tasks.Add(NewTask);
  99.         NewTask = new Task { Date = DateTime.Today };
  100.     }
  101.  
  102.     private void SelectionChanged(SelectionChangedEventArgs args)
  103.     {
  104.         if (args.AddedItems.Count > 0)
  105.         {
  106.             Messenger.Default.Send(new TaskSelectedMessage(args.AddedItems[0] as Task));
  107.             _navigationService.NavigateTo(new Uri(@"/View/EditPage.xaml", UriKind.Relative));
  108.         }
  109.     }
  110. }

The IDataService field is what we’ve defined just a minute ago, it gets instantiated through the constructor. INavigationService comes from the Cimbalino toolkit, it allows us to do page to page navigation from within the viewmodels. There’s a property of IList<Task> that one will hold all the available tasks, they are loaded at startup, also newly added tasks will be put in that list. There’s a property of type Task, his properties will be bound to the input fields on the new task form, when the user clicks save the property will be pushed to the dataservice to save it in the database. Talking about the save button, there are two RelayCommands (MVVM Light’s implementation of ICommand). One is for saving a new property and the second one is for navigating to the detail page when a task is selected. In the constructor both fields are set and the Task property is initialized, setting the date to today. Since our datepicker will be bound to this property it will automatically be set to today’s date. Loading all the tasks needs to be done asynchronous, since the constructor can’t be marked as async we’ll put the service call in a synchronous method and call that one from the constructor, that way we can use the async / await keywords. Saving a task is as easy as calling the SaveTask function on IDataService and adding the new task to the list, and reinitializing it afterwards to clear all the fields. You might want to think about adding some check here in case something goes wrong while saving to the DB (have it return a boolean for example), I’ll just be living on the edge here and assume this never fails Smile. For navigating to the detail page we’ll add a command to the SelectionChanged event of our LongListSelector. We use the MVVM Light messenger, some sort of implementation of the Observer pattern, to send over the selected item to anyone registered to listen to a message of type TaskSelectedMessage. The TaskSelectedMessage class is pretty basic.

Code Snippet
  1. public class TaskSelectedMessage : MessageBase
  2. {
  3.     public Model.Task Task { get; set; }
  4.  
  5.     public TaskSelectedMessage(Model.Task task)
  6.     {
  7.         Task = task;
  8.     }
  9. }

The class inherits from MessageBase, which is a class in the MVVM Light library, it has one property that is set in the constructor (that’s just to make life a bit easier).

In the MainViewModel, when the SelectionChanged event fires we send a message of this type containing the selected item, once the message is on its way we use the INavigationService to navigate to the detail page.

Here’s the  viewmodel for the editpage.

Code Snippet
  1. public class EditViewModel : ViewModelBase
  2. {
  3.     private readonly IDataService _dataService;
  4.     private readonly INavigationService _navigationService;
  5.  
  6.     /// <summary>
  7.     /// The <see cref="SelectedTask" /> property's name.
  8.     /// </summary>
  9.     public const string SelectedTaskPropertyName = "SelectedTask";
  10.  
  11.     private Task _selectedTask;
  12.  
  13.     /// <summary>
  14.     /// Sets and gets the SelectedTask property.
  15.     /// Changes to that property's value raise the PropertyChanged event.
  16.     /// </summary>
  17.     public Task SelectedTask
  18.     {
  19.         get
  20.         {
  21.             return _selectedTask;
  22.         }
  23.  
  24.         set
  25.         {
  26.             if (_selectedTask == value)
  27.             {
  28.                 return;
  29.             }
  30.  
  31.             RaisePropertyChanging(SelectedTaskPropertyName);
  32.             _selectedTask = value;
  33.             RaisePropertyChanged(SelectedTaskPropertyName);
  34.         }
  35.     }
  36.  
  37.     public RelayCommand UpdateTaskCommand
  38.     {
  39.         get { return new RelayCommand(UpdateTask); }
  40.     }
  41.  
  42.     public RelayCommand DeleteTaskCommand
  43.     {
  44.         get { return new RelayCommand(DeleteTask); }
  45.     }
  46.  
  47.     public EditViewModel(IDataService dataService, INavigationService navigationService)
  48.     {
  49.         _dataService = dataService;
  50.         _navigationService = navigationService;
  51.  
  52.         Messenger.Default.Register<TaskSelectedMessage>(this, msg => SelectedTask = msg.Task);
  53.     }
  54.  
  55.     private void UpdateTask()
  56.     {
  57.         _dataService.UpdateTask(SelectedTask);
  58.     }
  59.  
  60.     private void DeleteTask()
  61.     {
  62.         _dataService.DeleteTask(SelectedTask);
  63.     }
  64. }

The same fields can be found here (I could put them in a base class, would be cleaner but who cares about clean code anyway? – well you should all care!). One property in this viewmodel, to hold the selected task and bind its properties to the view. A few commands for update and delete, they just call their respective functions on the DataService passing in the selected Task. The interesting part here is in the constructor. The fields get set and we register the viewmodel to listen if the messenger has a message of type TaskSelectedMessage, if it does set the task in the message to the property. However, the viewmodel by default gets instantiated when we navigate to the view meaning that the message has left the building before the receiver has registered as a receiver so it won’t arrive. Let’s fix that shall we? When you’ve added the MVVM Light libraries through NuGet (or you used the MVVM Light project templates) there should be a ViewModelLocator class in your ViewModel folder. This class registers your viewmodels in the TinyIoc container. Registering those viewmodels has an overload that, when set to True, creates an instance of each viewmodel at application launch, meaning that the viewmodels register themselves on the messenger before any message can be send. Here are my viewmodel registrations (from the ViewModelLocator constructor).

Code Snippet
  1. SimpleIoc.Default.Register<MainViewModel>();
  2. SimpleIoc.Default.Register<EditViewModel>(true);

MainViewModel won’t get instantiated at registration but EditViewModel will. So that’s a problem solved. Next piece of the puzzle are those constructor parameters in the viewmodels. They get resolved by dependency injection, we register the correct types here in the ViewModelLocator and when the viewmodel constructor is called, the correct instances will get injected automagically.

Code Snippet
  1. if (ViewModelBase.IsInDesignModeStatic)
  2. {
  3.     // Create design time view services and models
  4.     SimpleIoc.Default.Register<IDataService, DesignService>();
  5. }
  6. else
  7. {
  8.     // Create run time view services and models
  9.     SimpleIoc.Default.Register<IDataService, DataService>();
  10.     SimpleIoc.Default.Register<INavigationService, NavigationService>();
  11. }

Take this for example, when we are in design mode (Blend for example) we can load an IDataService implementation that returns dummy data so that we can style our views very easily (code gets executed when running at designtime so even when you’re not using dummy data it’s a good idea to register these types in an if-block to prevent design time errors).

What everything in place, let’s have a look at the xaml and hook everything up. We’ll start with the MainPage.xaml and since XAML has a tendency of growing quite large, I’ll chop it in pieces. First thing a page needs in an MVVM scenario is a DataContext, meaning our ViewModel. This can be set from code behind (DataContext = new MainViewModel()) but that would just null out every use of the ViewModelLocator. We’ll set the datacontext from XAML.

Code Snippet
  1. <phone:PhoneApplicationPage x:Class="SqLitePoc.View.MainPage"
  2.                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.                             xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
  5.                             xmlns:behaviors="clr-namespace:Cimbalino.Phone.Toolkit.Behaviors;assembly=Cimbalino.Phone.Toolkit"
  6.                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  7.                             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
  8.                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  9.                             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  10.                             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  11.                             xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
  12.                             DataContext="{Binding Main,
  13.                                                   Source={StaticResource Locator}}"
  14.                             FontFamily="{StaticResource PhoneFontFamilyNormal}"
  15.                             FontSize="{StaticResource PhoneFontSizeNormal}"
  16.                             Foreground="{StaticResource PhoneForegroundBrush}"
  17.                             Orientation="Portrait"
  18.                             SupportedOrientations="Portrait"
  19.                             shell:SystemTray.IsVisible="True"
  20.                             mc:Ignorable="d">

The key here is DataContext="{Binding Main, Source={StaticResource Locator}}" this says to the view that its datacontext is bound to a property called Main and that property lives in a resource called Locator (that resource is defined in App.xaml). Now for the page itself, the page consists of a pivot control with two pivot pages, one for entering new tasks and one for viewing a list of all the tasks that have been created so far.

Code Snippet
  1. <!--  LayoutRoot is the root grid where all page content is placed  -->
  2. <Grid x:Name="LayoutRoot" Background="Transparent">
  3.     <!--  Bindable Appbar buttons  -->
  4.     <i:Interaction.Behaviors>
  5.         <behaviors:ApplicationBarBehavior>
  6.             <behaviors:ApplicationBarIconButton Command="{Binding SaveNewTaskCommand, Mode=OneTime}" IconUri="/Assets/AppBar/save.png" Text="Save Task" />
  7.         </behaviors:ApplicationBarBehavior>
  8.     </i:Interaction.Behaviors>
  9.  
  10.     <Grid.RowDefinitions>
  11.         <RowDefinition Height="Auto" />
  12.         <RowDefinition Height="*" />
  13.     </Grid.RowDefinitions>
  14.     <phone:Pivot Title="SQLite POC" Grid.Row="1">
  15.         <phone:PivotItem x:Name="NewTask" CacheMode="{x:Null}" Header="new task">
  16.             <StackPanel>
  17.                 <TextBlock Text="Title" TextWrapping="Wrap" />
  18.                 <TextBox x:Name="TextBoxTitle"
  19.                             Height="72"
  20.                             Text="{Binding NewTask.Title, Mode=TwoWay}"
  21.                             TextWrapping="Wrap" />
  22.                 <TextBlock Text="Complete by" TextWrapping="Wrap" />
  23.                 <toolkit:DatePicker Value="{Binding NewTask.Date, Mode=TwoWay}" />
  24.             </StackPanel>
  25.         </phone:PivotItem>
  26.         <phone:PivotItem x:Name="AllTasks" CacheMode="{x:Null}" Header="all tasks">
  27.             <phone:LongListSelector ItemTemplate="{StaticResource TaskListItemTemplate}" ItemsSource="{Binding Tasks}">
  28.                 <i:Interaction.Triggers>
  29.                     <i:EventTrigger EventName="SelectionChanged">
  30.                         <command:EventToCommand Command="{Binding SelectionChangedCommand}" PassEventArgsToCommand="True" />
  31.                     </i:EventTrigger>
  32.                 </i:Interaction.Triggers>
  33.             </phone:LongListSelector>
  34.         </phone:PivotItem>
  35.     </phone:Pivot>
  36. </Grid>

First thing in this snippet is a behavior for a bindable appbar button. The default appbar is not bindable, meaning that you can’t bind the buttons Command property to an ICommand on your viewmodel. This wasn’t the case in WP7 and it still isn’t in WP8, bit of a pain. Luckily, Cimbalino toolkit gives us an ApplicationBarBehavior, allowing us to bind our ICommands to the appbar, the only trade off we need to make is that the appbar buttons won’t be visible at design time but that’s a small trade-off in my opinion. We’ll add one button in the appbar, bind it to the SaveNewTaskCommand RelayCommand in MainViewModel and appoint it the save icon. Then there’s the pivot control, first pivotitem contains a stackpanel with a textbox for entering a task title and a datepicker (courtesy of the Windows Phone Toolkit) both are bound to properties of the NewTask property on the MainViewModel. Don’t forget to set the bind mode to TwoWay so that we can update the properties from our view. The second pivot item contains a list of all the tasks. Now, in WP8 they advice us to use the LongListSelector instead of the listbox that’s all great but at least make it behave more like a listbox and not some crippled dependency property missing piece of ****. The problem lies in the SelectedItem property, myself and many other XAML devs usually create a SelectedTask property and bind it to the SelectedItem property of the ListBox, the setter of that SelectedTask property would then be used to navigate to the detailspage. That was a clean, fast solution but the LongListSelector’s SelectedItem property is not a dependency property, meaning it cannot be bound so that’s not a viable solution anymore. Second option would be to bind an ICommand to the SelectionChanged event, again a no-go. There are some implementations of the LongListSelector floating around on the internet that has a bindable SelectedItem property so that would be a solution, another one is to add an EventToCommand behavior and binding the SelectionChanged event to the MainViewModel in the behavior (that’s right Windows 8 devs, we Windows Phone devs still get behaviors out of the box). I’m going with the EventToCommand solution, only thing I haven’t solved here is that when we navigate to the detail page, navigate back to the mainpage and click the same task again it won’t do anything anymore since that item still is the selected item so the selection doesn’t change and the event doesn’t fire. A solution here would be to use the messenger to send a message to the code behind of the view to set the SelectedItem property of the LongListSelector to null.

tl;dr version: LongListSelector kind off sucks but it can be solved.

The LongListSelector is bound to the Tasks collection, the ItemTemplate is defined in the resources part of the page

Code Snippet
  1. <phone:PhoneApplicationPage.Resources>
  2.     <DataTemplate x:Key="TaskListItemTemplate">
  3.         <StackPanel>
  4.             <TextBlock x:Name="Title"
  5.                        Style="{StaticResource JumpListAlphabetStyle}"
  6.                        Text="{Binding Title}"
  7.                        TextWrapping="Wrap" />
  8.             <TextBlock x:Name="Date"
  9.                        Margin="12,0,0,0"
  10.                        Text="{Binding Date}"
  11.                        TextWrapping="Wrap">
  12.                 <Run />
  13.                 <LineBreak />
  14.                 <Run />
  15.             </TextBlock>
  16.         </StackPanel>
  17.     </DataTemplate>
  18. </phone:PhoneApplicationPage.Resources>

That gives the list a nice look (as far as I can tell that is, I really really suck at designing apps…)

Last part on this page is the appbar itself, the button are defined using the Cimbalino toolkit but we need to actually put an appbar on the page, this sits between the resources and the LayoutRoot grid.

Code Snippet
  1. <!--  Buttons are defined using the behaviors in the Cimbalino toolkit to allow a bindable appbar  -->
  2. <phone:PhoneApplicationPage.ApplicationBar>
  3.     <shell:ApplicationBar IsMenuEnabled="True" IsVisible="True" />
  4. </phone:PhoneApplicationPage.ApplicationBar>

And that’s it for the MainPage, on to the final part of this post, the EditPage.xaml

First, the datacontext

Code Snippet
  1. DataContext="{Binding Edit, Source={StaticResource Locator}}"

Then the appbar buttons, again using Cimbalino (these need to sit in the LayoutRoot grid)

Code Snippet
  1. <!--  Bindable Appbar buttons  -->
  2. <i:Interaction.Behaviors>
  3.     <behaviors:ApplicationBarBehavior>
  4.         <behaviors:ApplicationBarIconButton Command="{Binding UpdateTaskCommand, Mode=OneTime}" IconUri="/Assets/AppBar/save.png" Text="Save Task" />
  5.         <behaviors:ApplicationBarIconButton Command="{Binding DeleteTaskCommand, Mode=OneTime}" IconUri="/Toolkit.Content/ApplicationBar.Delete.png" Text="Save Task" />
  6.     </behaviors:ApplicationBarBehavior>
  7. </i:Interaction.Behaviors>

And then there’s the controls

Code Snippet
  1. <!--  TitlePanel contains the name of the application and page title  -->
  2. <StackPanel Grid.Row="0" Margin="12,17,0,28">
  3.     <TextBlock Style="{StaticResource PhoneTextNormalStyle}" Text="SQLite POC" />
  4.     <TextBlock Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" Text="Edit Task" />
  5. </StackPanel>
  6.  
  7. <!--  ContentPanel - place additional content here  -->
  8. <Grid x:Name="ContentPanel"
  9.       Grid.Row="1"
  10.       Margin="12,0,12,0">
  11.     <StackPanel Margin="0,0,0,76">
  12.         <TextBlock Text="Title" TextWrapping="Wrap" />
  13.         <TextBox x:Name="TextBoxTitle" Height="72" Text="{Binding SelectedTask.Title, Mode=TwoWay}" TextWrapping="Wrap" />
  14.         <TextBlock Text="Complete by" TextWrapping="Wrap" />
  15.         <toolkit:DatePicker Value="{Binding SelectedTask.Date, Mode=TwoWay}" />
  16.     </StackPanel>
  17. </Grid>

That’s all pretty much the same as in the MainPage. And with that our small SQLite POC is finished.

Conclusion

In this post I’ve discussed SQLite in a Windows Phone 8 app. What you should take away from this is that as of Windows Phone 8 SQLite is a first class citizen, even more so when using the excellent sqlite-net library. Don’t forget to switch the platform when running on emulator or on a device, this is necessary because SQLite is a C++ library. I’ve also talked a bit about MVVM Light and the way I use it, I don’t claim that this is the best / only way to use the excellent MVVM implementation by Laurent Bugnion but it is one I feel comfortable with and that gives me great results. If you have any questions / remarks, feel free to drop a comment!

 

UPDATE:

for the LongListSelector, you can also use an extension of the control instead of defining a trigger, see http://stackoverflow.com/questions/14586521/bind-viewmodel-to-item-from-longlistselector-in-datatemplate/14600157#14600157 for more detail.
thanks for the tip Glenn (link to Glenn’s Twitter)!


Tags:

.Net | Binding | MVVM Light | Metro | Patterns | WP8 | WP7 | XAML

Copying Nokia’s Photobeamer with SignalR and WP8

by Nico

Some time ago Nokia launched a pretty impressive, almost magical app called “Photobeamer” (exclusive for the Nokia Lumia range). This is one of those apps that look very impressive and magical at first but when you start to think about it it’s not really that hard to figure out how this works. I thought about it and decided to hack together a copy of this.

If you have no clue what Photobeamer is all about, check out this video from Pocketnow

Disclaimer

Small remark about this video before we get started. The Nokia Photobeamer caches every image for about 30 days, meaning that if you select the same picture again it appears almost instantly, that’s what happens in this video. We will get nowhere near that performance since my concept here doesn’t do any caching. Also, they are streaming the image to the server (hence the fact that the picture is blurry at first and sharpens up later) we will just send over the entire image at once.

Puzzle pieces

All right, let’s get started. We need a few pieces to complete this puzzle. We need a Windows Phone app, we’ll need a service that takes care of sending the right picture to the right client and we’ll need a web client to display the QR code and the picture.

This schematic shows the pieces and their roles

The steps are:

  • webclient generates unique ID (guid)
  • webclient registers a group on the server with that ID
  • webclients uses ID to generate QR code
  • user launches Windows Phone app
  • user selects picture
  • user scans QR code to get the generated ID
  • phone app joins the group with the ID
  • phone app deserializes the picture
  • phone app sends the picture to the other group members
  • webclient receives picture, serializes it again and shows it

Lots of steps but it’s easier to build as you might think. We’ll start with the service as that’s the glue to hold everything together.

SignalR

Since we need some form of real-time communication I’ve decided to use SignalR. A snippet from the SignalR page that describes its functionality (http://signalr.net/):

ASP.NET SignalR is a new library for ASP.NET developers that makes it incredibly simple to add real-time web functionality to your applications. What is "real-time web" functionality? It's the ability to have your server-side code push content to the connected clients as it happens, in real-time.

You may have heard of WebSockets, a new HTML5 API that enables bi-directional communication between the browser and server. SignalR will use WebSockets under the covers when it's available, and gracefully fallback to other techniques and technologies when it isn't, while your application code stays the same.

All we need to get started is an empty web project and a nuget package use the package manager or the GUI

Code Snippet
  1. Install-Package Microsoft.AspNet.SignalR -Pre

SignalR, at the time of writing, is in Release Candidate, so we need to include prerelease versions in Nuget or you won’t find signalR at all. (although it’s prerelease, SignalR is working really well so no worries)

Before we start building the service we need to add some method calls in Global.asax.cs in the Application_Start method.

Code Snippet
  1. void Application_Start(object sender, EventArgs e)
  2. {
  3.     // Code that runs on application startup
  4.     AuthConfig.RegisterOpenAuth();
  5.  
  6.     GlobalHost.HubPipeline.EnableAutoRejoiningGroups();
  7.  
  8.     // Register the default hubs route: ~/signalr/hubs
  9.     RouteTable.Routes.MapHubs();
  10. }

The MapHubs() makes sure that the service calls are rerouted to the correct functions. The EnableAutoRejoiningGroups() is something that we need to do in this RC2 version but it will go away in RTM, see my StackOverflow question for more information.

SignalR uses the concept of Hubs, a hub is a class that contains all the service calls. Add a class called ImgHub to a folder called Hubs in the empty web project.

Code Snippet
  1. publicclassImgHub : Hub
  2. {
  3.     publicvoid Create(string guid)
  4.     {
  5.         Groups.Add(Context.ConnectionId, guid);
  6.     }
  7.     
  8.     publicvoid ShareImage(byte[] image, string guid)
  9.     {
  10.         Clients.OthersInGroup(guid).ReceiveImage(image);
  11.     }
  12.  
  13.     publicvoid Leave(string guid)
  14.     {
  15.         Groups.Remove(Context.ConnectionId, guid);
  16.     }
  17. }

That’s really not a lot of code for a service. First, every hub in a SignalR project needs to inherit from Microsoft.AspNet.SignalR.Hub. Next to that, every public method we declare in this class will be callable from the clients. First method is Create(), this takes in the unique ID that will be generated by the webclient in a minute. That ID is used to create a group. SignalR tries to add the connectionId from the client to a group with the guid as groupname. If that group doesn’t exist yet it will create it. The second method is ShareImage. This will take in the deserialized image (as a byte array) and that same guid again. Now we need to send that byte array to other clients so we call Clients.OthersInGroup, other options are Clients.All, Clients.Groups, Clients.Others, Clients.Caller, Clients.AllExcept. Plenty of choices but OthersInGroup suits our needs the best. The OthersInGroup returns a dynamic object, we can attach anything we want here. We want to call ReceiveImage() on the client, that method isn’t declared anywhere but since the object is dynamic the compiler won’t give us any trouble. And finally there’s a Leave() method allowing us to leave a group should it be needed.

The SignalR project can be hosted on any webhost that supports .net, for this demo I’ve used Windows Azure Websites.

Webclient

1/3th done, the second part is the webclient. This is a normal website using asp.net webforms. It’s responsible for generating the ID, passing it to SignalR to create the group, get a QR code and receive the image.

First thing we need is the project, second is a SignalR client and the SignalR Javascript library (yes we’ll be needing Javascript and no I’m not proud of this…)

First some HTML code, the Default.aspx page is nothing fancy, it will only show the QR code.

Code Snippet
  1. <body>
  2.     <formid="form1"method="post"action="ImagePage.aspx">
  3.         <inputtype="hidden"id="hiddenByteArray"name="hiddenByteArray"/>
  4.         <div>
  5.             <imgsrc="/imagehandler.ashx"style="text-align: center"/>
  6.         </div>
  7.     </form>
  8. </body>

Notice the imagehandler.ashx reference? That’s a generic handler that will take care of generating the QR code and passing it into this img tag. Generic handler is a file type that you can add through Visual Studio, here’s the code for imagehandler.ashx.

Code Snippet
  1. publicclassImageHandler : IHttpHandler, IRequiresSessionState
  2. {
  3.     publicvoid ProcessRequest(HttpContext context)
  4.     {
  5.         var guid = HttpContext.Current.Session["InstanceGuid"];
  6.  
  7.         string url = string.Format(@"http://api.qrserver.com/v1/create-qr-code/?size=300x300&data={0}", guid);
  8.  
  9.         WebClient client = newWebClient();
  10.         var bytes = client.DownloadData(newUri(url));
  11.  
  12.         context.Response.OutputStream.Write(bytes, 0, bytes.Length);
  13.         context.Response.ContentType = "image/JPEG";
  14.     }
  15.  
  16.     publicbool IsReusable
  17.     {
  18.         get
  19.         {
  20.             returnfalse;
  21.         }
  22.     }
  23. }

We’re getting our guid from the session object (how it got there, we’ll see in a minute) that’s why we need the IRequiresSessionState interface. The ProcessRequest method we get from IHttpHandler and will get executed when the handler is called. So we first get the guid from the session, then we’ll build a url to qpi.qrserver.com, an api that takes in a value and generates a QR code from that value. We use WebClient to get the data from that url, the byte array that we receive from it will be our generated QR code, we write it to the outputstream of the page’s context and set the type to be an image/JPEG. There should be some error handling here if you’re using this for production code (sometimes the qrserver API takes to long and times out).

Next, we’ll have a look at Default.aspx.cs.

Code Snippet
  1. protectedvoid Page_Load(object sender, EventArgs e)
  2. {
  3.     var guid = Guid.NewGuid();
  4.     HttpContext.Current.Session["InstanceGuid"] = guid.ToString();
  5. }

Not much going on, we generate a new Guid and set it to the current session object.

Now, let’s have a look at connection the webclient to the signalR server and getting ready to receive the image.

Warning: the next part contains javascript code…

In Default.aspx we add this script

Code Snippet
  1. <scriptsrc="Scripts/jquery-1.7.1.min.js"></script>
  2. <scriptsrc="Scripts/jquery.signalR-1.0.0-rc2.min.js"></script>
  3. <scriptsrc="http://pbclone.azurewebsites.net/signalr/hubs/"type="text/javascript"></script>
  4. <scripttype="text/javascript">
  5.     $(function () {
  6.         $.connection.hub.url = 'http://pbclone.azurewebsites.net/signalr';
  7.         //$.connection.hub.url = 'http://localhost:4341/signalr';
  8.         // Proxy created on the fly
  9.         var mainHub = $.connection.imgHub;
  10.         var guid = '<%=HttpContext.Current.Session["InstanceGuid"] %>';
  11.  
  12.         // Declare a function on the hub so the server can invoke it
  13.         mainHub.client.receiveImage = function (imageArray) {
  14.             //window.location = "/ImagePage.aspx?arr=" + imageArray;
  15.             $('#hiddenByteArray').val(imageArray);
  16.             $('#form1').submit();
  17.         };
  18.        
  19.         // Start the connection
  20.         $.connection.hub.start().done(function () {
  21.             mainHub.server.create(guid);
  22.         });
  23.     });
  24. </script>

First, we need to add jquery and the SignalR javascript library to our page. The third included script comes from wherever you host your SignalR service. The /signalr/hubs/ will be a proxy in javascript that contains the methods in the hub, allowing us to use them from our clients (try browsing to that url and have a look inside the javascript). $.connection comes from the SignalR javascript library, we set the correct url and get the correct hub. We’ll also use a bit of inline asp.net to get the guid from the session. Remember in the SignalR part that we called ReceiveImage on the dynamic object? Line 13 is where we declare a callback handler on that method call. We set the received value, which will be a byte array, to a hidden field and POST the form. Those handlers need to be set before we call the start() method on the hub. <yourhub>.client is where all your client side callbacks are registered. <yourhub>.server is where all server side methods can be called, those methods are loaded from the /signalr/hubs/ proxy. On line 20 we start the connection to the hub, once we’re connected we’ll call the create method and pass the guid in to create and join the group.

We’ll need a second page in this webclient to actually show the image. Only one element on the page, an img element.

Code Snippet
  1. <body>
  2.     <formid="form1"runat="server">
  3.     <div>
  4.         <imgsrc="/ByteArrayHandler.ashx"style="text-align: center"/>
  5.     </div>
  6.     </form>
  7. </body>

The img element uses a second generic handler that will take care of deserializing the byte array back into an image.

Code Snippet
  1. publicclassByteArrayHandler : IHttpHandler, IRequiresSessionState
  2. {
  3.  
  4.     publicvoid ProcessRequest(HttpContext context)
  5.     {
  6.         string base64String = HttpContext.Current.Session["ByteArray"].ToString();
  7.         byte[] convertedFromBase64 = Convert.FromBase64String(base64String);
  8.  
  9.         context.Response.OutputStream.Write(convertedFromBase64, 0, convertedFromBase64.Length);
  10.         context.Response.ContentType = "image/JPEG";
  11.     }
  12.  
  13.     publicbool IsReusable
  14.     {
  15.         get
  16.         {
  17.             returnfalse;
  18.         }
  19.     }
  20. }

We’ll get the byte array from the session object. SignalR encodes arrays with Base64 encoding so we need to decode that first, once that’s done we can just write the byte array into the outputstream as a JPEG, just like we did with the QR code. Onto the ImagePage.aspx.cs to see how the byte array goes into the session object

Code Snippet
  1. protectedvoid Page_Load(object sender, EventArgs e)
  2. {
  3.     NameValueCollection postedValues = Request.Form;
  4.  
  5.     var base64String = postedValues["hiddenByteArray"];
  6.     HttpContext.Current.Session["ByteArray"] = base64String;
  7. }

We get our POST values from Request.Form, look for the hidden field called hiddenByteArray and place its value in the session.

We now have our service and one client complete, all that’s left is building a Windows Phone application that connects to that same group on that same service and send the picture over.

Windows Phone client

For this we’ll need a Windows Phone 8 project as SignalR has no official support for Windows Phone 7. Make sure that you have the latest version of Nuget installed or it won’t find the correct SignalR assembly for Windows Phone 8 (thanks David Fowler for pointing this out).

Add the SignalR.Client assembly to the project. Here’s the XAML for the MainPage.

Code Snippet
  1. <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
  2.     <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
  3.     <TextBlock x:Name="StatusText" Text="Not connected" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
  4. </StackPanel>
  5.  
  6. <!--ContentPanel - place additional content here-->
  7. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  8.     <Rectangle x:Name="_previewRect"
  9.        Margin="0"
  10.        Height="800"
  11.        Width="600"
  12.        HorizontalAlignment="Center"
  13.        VerticalAlignment="Center">
  14.         <Rectangle.Fill>
  15.             <VideoBrush x:Name="_previewVideo">
  16.                 <VideoBrush.RelativeTransform>
  17.                       <CompositeTransform
  18.                 x:Name="_previewTransform" CenterX=".5" CenterY=".5" />
  19.                 </VideoBrush.RelativeTransform>
  20.             </VideoBrush>
  21.         </Rectangle.Fill>
  22.     </Rectangle>
  23.     <ListBox Margin="10" x:Name="_matchesList" FontSize="30" FontWeight="ExtraBold" />
  24. </Grid>

I use one of the default textboxes in the page’s header for a connection status. In the content grid we place a rectangle filled with a VideoBrush, this will be used to scan the QR code, Let’s have a look at the code for the WP app.

First we declare some fields

Code Snippet
  1. privatestring _guid;
  2. privatePhotoChooserTask _photoChooserTask;
  3. privateIHubProxy _mainHub;
  4. privateHubConnection _connection;
  5. privatereadonlyDispatcherTimer _timer;
  6. privatePhotoCameraLuminanceSource _luminance;
  7. privateQRCodeReader _reader;
  8. privatePhotoCamera _photoCamera;
  9. privateStream _imgStream;

I’ll explain these when we encounter them. Now for the page’s constructor

 

Code Snippet
  1. public MainPage()
  2. {
  3.     InitializeComponent();
  4.  
  5.     _photoCamera = newPhotoCamera();
  6.     _photoCamera.Initialized += OnPhotoCameraInitialized;
  7.     _previewVideo.SetSource(_photoCamera);
  8.     CameraButtons.ShutterKeyHalfPressed += (sender, args) => _photoCamera.Focus();
  9.  
  10.     _photoChooserTask = newPhotoChooserTask();
  11.     _photoChooserTask.Completed += photoChooserTask_Completed;
  12.     _photoChooserTask.Show();
  13.  
  14.     _timer = newDispatcherTimer
  15.                  {
  16.                      Interval = TimeSpan.FromMilliseconds(250)
  17.                  };
  18.  
  19.     _timer.Tick += (o, arg) => ScanPreviewBuffer();
  20. }

First we initialize a PhotoCamera instance. _previewVideo is the VideoBrush set in the rectangle, we set its source to the PhotoCamera instance. On line 8 we state that when the hardware camera button is half pressed we focus the camera, just a small helper for when the app has troubles reading the QR code. The next part is calling the PhotoChooserTask, this task gives us access to the albums and pictures on the device. We’ll need a timer as well, every timer tick we’ll check if the camera preview window contains a QR code. We’ve declared some event handlers in this constructor, let’s go over them one by one. We’ll start with the OnPhotoCameraInitialized.

Code Snippet
  1. privatevoid OnPhotoCameraInitialized(object sender, CameraOperationCompletedEventArgs e)
  2. {
  3.     int width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
  4.     int height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);
  5.     _photoCamera.FlashMode = FlashMode.Off;
  6.  
  7.     _luminance = newPhotoCameraLuminanceSource(width, height);
  8.     _reader = newQRCodeReader();
  9.  
  10.     Dispatcher.BeginInvoke(() =>
  11.     {
  12.         _previewTransform.Rotation = _photoCamera.Orientation;
  13.     });
  14. }

We get the resolution’s width and height and turn the flash off. The PhotoCameraLuminanceSource on line 7 is a custom class that will provide us with a previewbuffer that we can fill. Here’s the class

Code Snippet
  1. publicclassPhotoCameraLuminanceSource : LuminanceSource
  2. {
  3.     publicbyte[] PreviewBufferY { get; privateset; }
  4.  
  5.  
  6.     public PhotoCameraLuminanceSource(int width, int height)
  7.         : base(width, height)
  8.     {
  9.         PreviewBufferY = newbyte[width * height];
  10.     }
  11.  
  12.  
  13.     publicoverridesbyte[] Matrix
  14.     {
  15.         get { return (sbyte[])(Array)PreviewBufferY; }
  16.     }
  17.  
  18.  
  19.     publicoverridesbyte[] getRow(int y, sbyte[] row)
  20.     {
  21.         if (row == null || row.Length < Width)
  22.         {
  23.             row = newsbyte[Width];
  24.         }
  25.  
  26.  
  27.         for (int i = 0; i < Height; i++)
  28.             row[i] = (sbyte)PreviewBufferY[i * Width + y];
  29.  
  30.  
  31.         return row;
  32.     }
  33. }

The class inherits from LuminanceSource which comes from the Google zxing project. Zxing is a library to decode QR and barcode images, it has a .NET port on codeplex (http://zxingnet.codeplex.com/) that port is what I use in this project and that’s where the LuminanceSource comes from. That’s also where the QRCodeReader class lives.

Next event handler that we attached in the constructor is the photoChooserTask_Completed

Code Snippet
  1. void photoChooserTask_Completed(object sender, PhotoResult e)
  2. {
  3.     if (e.TaskResult == TaskResult.OK)
  4.     {
  5.         _imgStream = e.ChosenPhoto;
  6.  
  7.         _timer.Start();
  8.     }
  9. }

If the task returns succesfully we’ll set the chosen photo, which arrives here as a stream, to the _imgStream field and we start the timer. Now on every timer tick (every 250 milliseconds in this example) we will scan the previewbuffer for QR codes.

Code Snippet
  1. privatevoid ScanPreviewBuffer()
  2. {
  3.     if (_guid != null)
  4.     {
  5.         _timer.Stop();
  6.  
  7.         SendImage();
  8.     }
  9.  
  10.     try
  11.     {
  12.         _photoCamera.GetPreviewBufferY(_luminance.PreviewBufferY);
  13.         var binarizer = newHybridBinarizer(_luminance);
  14.         var binBitmap = newBinaryBitmap(binarizer);
  15.         var result = _reader.decode(binBitmap);
  16.  
  17.         Dispatcher.BeginInvoke(() =>
  18.                                    {
  19.                                        _guid = result.Text;
  20.                                    });
  21.     }
  22.     catch
  23.     {
  24.  
  25.     }
  26. }

First thing we do here is checking if we already have a guid, if we do we stop the timer and send the image to the SignalR service. If _guid is still null we’ll get the previewbuffer and try to decode it, if there’s no QR code in the previewbuffer it will throw an exception, hence the empty catch block. When we can decode  we’ll go to the SendImage() method.

Code Snippet
  1. privateasyncvoid SendImage()
  2. {
  3.     if (_connection == null || _connection.State != ConnectionState.Connected)
  4.     {
  5.         await SetupSignalRConnection();
  6.     }
  7.  
  8.     if (_connection.State == ConnectionState.Connected || _connection.State == ConnectionState.Reconnecting)
  9.     {
  10.         MemoryStream s = newMemoryStream();
  11.         _imgStream.CopyTo(s);
  12.         _mainHub.Invoke("ShareImage", newobject[]{s.ToArray(), _guid});
  13.     }
  14.     else
  15.     {
  16.         MessageBox.Show("not connected");
  17.     }
  18. }

If there’s no active connection, we’ll call the SetupSignalRConnection() method. if there is and we are connected we copy the imagestream into a MemoryStream and we invoke the ShareImage() method on the SignalR server, passing in the memorystream, converted into a byte array, and the guid we got from the qr code.

Now for the connection to the server.

Code Snippet
  1. privateasyncTask SetupSignalRConnection()
  2. {
  3.     _connection = newHubConnection("http://pbclone.azurewebsites.net/");
  4.     _connection.StateChanged += ConnectionOnStateChanged;
  5.     _mainHub = _connection.CreateHubProxy("imghub");
  6.  
  7.     await _connection.Start();
  8.  
  9.     _mainHub.Invoke("Create", _guid);
  10. }

We instantiate a new HubConnection with the url to the service as parameter. We generate a proxy for the hub we want to use and we call the start() method on the connection. It will connect to the hub, get the javascript proxy and translate it into a .net proxy. We then invoke the Create() method and pass in the guid so that our Windows Phone client joins the same group as the web client. The ConnectionOnStateChanged event handler is only used to update the textblock on the page to show whether or not we’re connected.

Code Snippet
  1. privatevoid ConnectionOnStateChanged(StateChange stateChange)
  2. {
  3.     switch (stateChange.NewState)
  4.     {
  5.         caseConnectionState.Connecting:
  6.             StatusText.Text = "Connecting...";
  7.             break;
  8.         caseConnectionState.Connected:
  9.             Dispatcher.BeginInvoke(() => StatusText.Text = "Connected");
  10.             break;
  11.         caseConnectionState.Reconnecting:
  12.             Dispatcher.BeginInvoke(() => StatusText.Text = "Reconnecting...");
  13.             break;
  14.         caseConnectionState.Disconnected:
  15.             Dispatcher.BeginInvoke(() => StatusText.Text = "Disconnected");
  16.             break;
  17.     }
  18. }

And that’s it, we can now start sending images to any device with a browser and an internet connection.

Conclusion

In this post I’ve tried to demystify the magic from Nokia’s Photobeamer app. It is a really cool app but when you take it apart, it’s not that magical. Like a lot of impressive looking tech it just combines a bunch of existing techs into something no one else thought of.

The code in this article is all my own, I have no clue how the Nokia app actually works and what technology they are using, I’m only mimicking their behavior.

Update: I've uploaded the project to Github https://github.com/NicoVermeir/photobeamerclone


Tags:

.Net | Metro | signalr | Web development | WP8 | XAML

Getting home with Windows Phone 8 and NFC

by Nico

Imagine this, you’re somewhere you’ve never been before and you need your phone to navigate you home but you need a quick getaway and don’t have time to enter the address manually. Or you’re taking the boy/girl of your dreams home after a great date and want to impress them with some technological stuff (because geeks are the new sexy). In both scenarios NFC can come to the rescue. In this article I’m going to explain how you can program an NFC tag to launch your navigation app and navigate you home. (NOTE: this has been tested on a Nokia Lumia 920 with Nokia Drive).

First, the prerequisites. We need an NFC capable Windows Phone 8 device with navigation software. We also need a blank, NDEF formatted, writable NFC tag (I got mine from RapidNFC). We’ll also need a dataconnection to fetch our coordinates (only for writing the NFC tag).

Next, the pieces of the puzzle. In this case there are three things that need to be taken care of. First we need to be able to enter an address in an app and get the longitude/latitude coordinates for that address. Second, we need to write the instruction for launching the navigations app and navigating to those coordinates to an NFC tag and third we need our phone to actually launch the app and navigate to the received coordinates. Now to make that last part work we only need to make sure we have an NFC capable phone, have NFC enabled in Settings and that we have navigational software installed.

Enough planning, let’s get to work. First the UI, I‘m going with two TextBlocks, one to enter the address and one that will show the coordinates just to see if that worked. I also need two buttons, one for fetching the coordinates and one for writing the NFC tag. Here’s the XAML

Code Snippet
  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2.     <StackPanel>
  3.         <TextBlock Text="Address" />
  4.         <TextBox x:Name="TextBoxAddress" />
  5.                         <TextBlock Text="Coordinates" />
  6.            <TextBox x:Name="TextBoxCoordinates" />
  7.         
  8.         <StackPanel Orientation="Horizontal">
  9.             <Button Content="Get Coordinates" Click="GetCoordinatesButtonClick" />
  10.             <Button Content="Write NFC tag" Click="WriteTagButtonClick" />
  11.         </StackPanel>
  12.     </StackPanel>
  13. </Grid>

With this as the final result

How this works, we enter an address in the top TextBox and click the “Get Coordinates” button. This will use the Microsoft.Phone.Maps functionality to translate that address into coordinates, those coordinates will show up in the bottom TextBox. When we click the “Write NFC tag” button the app will wait for a writable NFC tag, once that’s detected the data will be written on it. All it takes then is a tap on the tag and the phone will take you home.

Before we dive into code we need to add some capabilities. Using the Maps namespace and using NFC requires two capabilities, double-click the WMAppManifest.xml file and select these capabilities.

This will keep us away from any UnauthorizedExceptions.

On to the code we go, we’ll start with declaring some private fields.

Code Snippet
  1. private GeoCoordinate _coordinate;
  2. private ProximityDevice _device;

After that, we go to the “Get Coordinates” button.

Code Snippet
  1. private void GetCoordinatesButtonClick(object sender, RoutedEventArgs e)
  2. {
  3.     string address = TextBoxAddress.Text.Trim();
  4.  
  5.     if (address == string.Empty)
  6.     {
  7.         MessageBox.Show("Address cannot be empty!");
  8.         return;
  9.     }
  10.  
  11.     GeocodeQuery query = new GeocodeQuery
  12.                              {
  13.                                  GeoCoordinate = new GeoCoordinate(0, 0),
  14.                                  SearchTerm = address
  15.                              };
  16.  
  17.     query.QueryCompleted += (o, args) =>
  18.                                 {
  19.                                     if (args.Result == null)
  20.                                     {
  21.                                         TextBoxCoordinates.Text = "No coordinates found";
  22.                                         return;
  23.                                     }
  24.                                     _coordinate = args.Result[0].GeoCoordinate;
  25.                                     TextBoxCoordinates.Text = string.Format("Lat: {0} / Lon: {1}",
  26.                                         args.Result[0].GeoCoordinate.Latitude.ToString(),
  27.                                         args.Result[0].GeoCoordinate.Longitude.ToString());
  28.                                 };
  29.     query.QueryAsync();
  30. }

First thing we need to do is verify if an address was actually entered in the TextBlock. When that’s verified we declare a GeocodeQuery and initialize it with a new GeoCoordinate and pass the address as a SearchTerm. When the query completes we check if there’s a result. The query should return a result of type IList<MapLocation> the first element in the list is the one we need, and from this first item we need the GeoCoordinate property, we’ll put that one in the _coordinate field. We call the QueryAsync() method on GeocodeQuery to get the result. For some reason QueryAsync returns void, meaning we can’t just await it. We need to do this the oldschool way and use the QueryCompleted event handler.

With that, the first part of our puzzle is solved. We can go from an address to a coordinate. Now we just need a way to get this coordinate and the navigation app launch instruction onto an NFC tag. Let’s have a look at what happens when the “Write NFC tag” button is clicked.

Code Snippet
  1. private void WriteTagButtonClick(object sender, RoutedEventArgs e)
  2. {
  3.     _device = ProximityDevice.GetDefault();
  4.  
  5.     if (_device == null)
  6.     {
  7.         MessageBox.Show("NFC not detected, is it disabled?");
  8.         return;
  9.     }
  10.  
  11.     TextBlockStatus.Text = "NFC detected, waiting for writable tag";
  12.  
  13.     _device.SubscribeForMessage("WriteableTag", (device, message) =>
  14.                     {
  15.                         Deployment.Current.Dispatcher.BeginInvoke(() =>
  16.                                         {
  17.                                             TextBlockStatus.Text = "writable tag detected";
  18.                                         });
  19.                         WriteTag();
  20.                     });
  21. }

There’s some NFC magic going on here. First we instantiate a ProximityDevice instance and activate the proximity provider. If, at that point, _device is null it means that the Windows Phone device either has no NFC capabilities or they are disabled in Settings > Tap & Send. If _device is not null we have successfully initialized NFC. Line 13 is a bit special. We call the SubscribeForMessage() method on the ProximityDevice. What happens is, when the NFC provider reads a tag it sends a message, we subscribe to the “WritableTag” message because it’s the only thing we can use in this case. If you want a complete list of all supported message types, have a look at MSDN.Since the subscription doesn’t live on the UI thread we need to use the Dispatcher in order to update the TextBlock that hold the status. The WriteTag() method gets called when a writable NFC tag is detected.

Code Snippet
  1. private void WriteTag()
  2. {
  3.     string uri = string.Format(@"ms-drive-to:?destination.latitude={0}&destination.longitude={1}",
  4.         _coordinate.Latitude.ToString(CultureInfo.InvariantCulture),
  5.         _coordinate.Longitude.ToString(CultureInfo.InvariantCulture));
  6.  
  7.     var writer = new DataWriter
  8.                          {
  9.                              UnicodeEncoding = UnicodeEncoding.Utf16LE
  10.                          };
  11.  
  12.     writer.WriteString(uri);
  13.  
  14.     _device.PublishBinaryMessage("WindowsUri:WriteTag", writer.DetachBuffer(), (sender, id) =>
  15.         Dispatcher.BeginInvoke(() => TextBlockStatus.Text = "Tag written"));
  16. }

This method is the piece of magic that glues all pieces together. We start by setting the Uri that will launch when the tag is tapped. “ms-drive-to” means we need whatever app is registered to the drive-to command (you can also get walking directions by using “ms-walk-to”) the rest of the string are parameters we’re passing into that app. We are passing the coordinates into the app, passing those in means that the app knows we want to navigate and where we want to go. We also need a DataWriter with Utf16LE encoding (this is the encoding needed for writing uri messages to NFC tags). We fill the buffer of the DataWriter with the uri string we’ve constructed a second ago and we publish it through the ProximityDevice as a binary message. The PublishBinaryMessage() method takes in a messagetype and an implementation of IBuffer, provided by the DataWriter in this case. In an overload the method also takes a method that fires when the publish is completed, we use this event handler to update our UI.

That’s all folks, with a bit of tinkering we’ve combined two possibilities of the Windows Phone 8 platform in a very cool, almost “magical” trick. I've got my NFC sticker in my car, impressing people wherever I go and now you can all be as cool as I am Smile you’re welcome.

To finish of, some action shots of the app.


Coordinates detected


Tapped a programmed tag


Navigation started


Tags:

NFC | .Net | Devices | WP8 | XAML

Windows Phone 8 and Fiddler

by Nico

Fiddler and the WP8 emulator

Fiddler is a great tool for capturing network traffic. I find it especially useful when I’m working with services. It sniffs out your network traffic and allows you to dig into every incoming or outgoing request. You can even create requests from inside the tool. The tool itself is free to use and can be downloaded from https://fiddler2.com/fiddler2/

So how does it work? Fiddler installs a proxy on your machine (default on port 8888). That proxy intercepts all network traffic going from and to the machine it’s installed on. That traffic gets displayed in the Fiddler UI. The proxy captures the traffic, sends it to the application and let the traffic itself pass to the original destination. This image shows the normal client – internet situation (top half) and the situation with Fiddler installed (bottom half).

Makes sense? Nothing to difficult about this. What I just explained here is the basic functionality of Fiddler. Only monitoring your local traffic. The Windows Phone 8 emulator runs as a Hyper-V virtual machine, meaning it identifies itself as a separate device on the network. But that’s not really a problem, Fiddler in al its greatness can monitor remote devices as well. Here’s how to enable it.

First, start Fiddler and go to Tools > Fiddler options. Go to tab “Connections” and check the “Allow remote computers to connect” option.

Click OK, back on the Fiddler main screen, you’ll notice a textbox underneath the list of captured requests (a black one). That’s called the QuickExec box, it can be used to set preferences. In our case we need to add a hostname to our proxy. The hostname we need to add is the one from the Hyper-V host that is running the Windows Phone emulator, your developer machine in other words. Since all traffic from the Windows Phone emulator goes through our developer machines we need to attach Fiddler to our pc. The default localhost connection won’t work so we need to attach the Fiddler proxy to the network name.

In the QuickExec box enter this command

prefs set fiddler.network.proxy.registrationhostname <your computername>

With that done, restart Fiddler and the Windows Phone emulator and behold the emulator’s traffic getting sniffed. As you can see on the screenshot below, if I use the mobile browser in the emulator to go to my blog Fiddler captures all the images, pages, scriptfiles etc. that are getting loaded. If I select one, the user agent clearly points to the Windows Phone 8 browser.

Note that it doesn’t just captures the emulator’s traffic, all the localhost traffic is still captured as well.

Keep in mind that if you close Fiddler now there’s a chance that the Windows Phone emulator won’t have network access anymore, that’s because at startup it configured the Fiddler proxy as gateway, closing Fiddler means disabling the proxy. Simply restart the emulator and it should work fine again.

This is all great stuff, but eventually we’ll run into a situation where we need to sniff network traffic but for some reason we can’t use the emulator. With Fiddler we can also sniff the network traffic from an actual Windows Phone device, provided the machine running Fiddler and the Windows Phone are connected to the same network.

Fiddler and WP8 devices

To do this, setup Fiddler the same way as we did for the emulator. When that’s done, on you Windows Phone device go to Settings > WiFi. Select the wireless network that your phone is connected to and enable the Proxy. Set the proxy url to the IP address or the hostname of the computer running Fiddler and the port to 8888.

Fire up Fiddler, fire up the mobile browser on your phone and be amazed!

If you’re decrypting HTTPS traffic you might need to install the Fiddler certificate on your phone, the browser will prompt you to install it. Before testing your app with HTTPS, try the browser first so the certificate gets installed. Do be aware that every Fiddler installation generates its own certificate (they are self-signed so you might get a security warning, in this case its perfectly safe to ignore that warning) so you might need to install a new one when you use Fiddler on another machine.

 

Conclusion

In this post we’ve talked about using Fiddler, a great tool for sniffing and decrypting network requests, with both the Windows Phone 8 emulator and Windows Phone 8 devices. It’s really easy to setup and a great asset when working or developing services.

A few remarks to end this post:

If you ever change your computer’s hostname Fiddler will stop capturing Windows Phone network. Use the prefs set fiddler.network.proxy.registrationhostname <your computername> command again in the QuickExec box with the new hostname and Fiddler will happily continue its work.

If you computer is joined to a domain that has IPSEC security setup you will need to ask the administrator to add a IPSEC Boundary Computer exception for your computer.

Happy sniffing!


Tags:

.Net | WP7 | WP8 | Devices

  Log in

About the author

Hi,

My name is Nico, I’m an MVP Windows Platform 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

 

mvp

 

 

MeetLogo

 

MVBLogo

mybook

 

Month List