Nico's digital footprint

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

Porting a real win8 app to WP8–part 1

by Nico

A few weeks ago the first version of my Windows 8 app (finally) hit the store (download it here).  From the start I wanted to port this application to Windows Phone 8 as well but I didn’t keep that in mind when developing the app. Some time ago, the portable HttpClient was released in a beta version and to me that was the perfect time to see how useful the portable class libraries (PCL) really are.

Most of the information available on the internet on sharing code between Windows Store and Windows Phone apps have those really small basic projects, good stuff to get started, but I want to port an entire, finished project to another platform. Perfect content for some blog posts so I’ll be documenting my progress here on my blog, hopefully it will be to some use.

The app

The app is called Comic Cloud and is a continuation of my very first Windows Phone 7 app ever. It allows users to search for anything related to comic books (volumes, issues, artists, characters, locations, …) and provides a whole bunch of information on the topic. The data comes from a community driven website (think Wikipedia for comics) called ComicVine. They have a great REST API with great documentation so that was perfect. On the other hand, and this is new in the Windows 8 version, users can start tracking their own collection of comic books and keep track of which issues in their collection are already read. This data is saved on Azure by using the awesome Azure Mobile Services, authentication happens with the Microsoft Account (single sign-on). So researching and collection are the two keywords of the application. Since the API is REST based, I make extensive use of the HttpClient class to make the API calls.

Architecture

As for architecture, all libraries are Windows Store class libraries and then off course there’s the app itself, written in C# and XAML. This image shows the projects and their dependencies.

(The app was called ComicDB in its begin stages, the namespaces stayed but the app title was changed to Comic Cloud)

The solution exists of five projects, first there’s the app itself using MVVM Light, win8nl for winRT behaviors (written by Joost van Schaik), MarkedUp for analytics, Callisto for settings fly-out, the Live SDK for the User class and the Telerik RAD controls for their controls (obviously).

The Model project contains all classes, there’s the ComicVine classes (thank God for paste JSON as class…) and some classes for RSS feeds and links.

Since I want to limit the amount of data stored in my WAMS database, I only save the userID and the link to the ComicVine API for each item. For that I needed a second version of some classes, that’s what the DTO project is for.

The framework is a project that I can reuse in other projects without changing anything, all classes that are app independent. Things like the RestClient (providing generic CRUD functions), the GroupInfoList for grouped gridviews, navigationservice to navigate between pages and so on. The ComicVineHelper is an extension method that changes the casing of some object to be compatible with the way the ComicVine API works. All these classes are implementing interfaces, so that will be a big plus when I start porting.

The SDKBroker takes all the different services I use and puts them together in one big SDK that’s easy to use from the app.

The idea

So the idea was to take all those libraries, put them in PCL libraries and reference them from both the Windows Store app and the Windows Phone app. Next to that I wanted to use the portable version of MVVM Light to share my viewmodels over both projects as well. Turns out that, as usual, a good idea is stopped by technical limitations.

The problem

The problem is the difference between Windows 8 and Windows Phone, they don’t share their entire codebase. Meaning I can’t reuse all my code in a PCL. Also the Azure Mobile Services SDK has no portable version, so same problem there.

The solution is abstractions, create an interface for every class that isn’t compatible with the PCL projects and implement them in a platform specific library. The PCLs I’m using only target .net 4.5, winRT and WP8 so a lot of problems are already taken care of by not selecting WP7.X compatibility.

The road so far

I wanted to start out by replacing MVVM Light with the PCL version. This turned out to be easier said than done, the initial project was started from the MVVM Light template so I threw out the references to MVVM Light and added the PCL version through NuGet. Visual Studio went quite mad and started throwing all sorts of weird build errors, I eventually found out that the win8nl library also includes the MVVM Light assemblies and those conflicted with the PCL versions. But I needed the win8nl assembly for the eventtocommand behaviors in WinRT so that posed a big problem. Luckily there’s the winRTBehaviors assembly that contains the logic to do behaviors but it doesn’t include the actual eventtocommand one. The solution was to go to the Codeplex site of win8nl and copy the behavior classes from there and put them in my framework project. One problem solved.

The next step was to add a PCL for the Framework and SDKBroker projects, the Model was already a PCL so that one could stay as it was. The PCL libs got named ComicDB.Framework and ComicDB.SDKBroker, they contain a combination of interfaces and classes. Everything that couldn’t be made portable was abstracted into an interface and implemented in platform specific libraries called ComicDB.Framework.WinRT and ComicDB.SDKBroker.WinRT. The classes that needed abstraction were the NavigationService, Network helper, WAMS service class and Service helper. Thanks to the new portable HttpClient assembly I could copy my RestClient class to a PCL without any adjustments.

With some tinkering I got the project to build and run again and I saw that it was good. The time had come to move my ViewModels over to a PCL. I added a new PCL project called ComicDB.ViewModel (same namespace as my VMs already had) and added the portable MVVM Light version. The ViewModelLocator can’t be moved since it needs to register all the correct interface implementations into the IOC container, so I’ll have a separate Locator class for Win8 and WP8. As I started moving ViewModels I quickly ran into a navigational problem, my viewmodels have navigation logic and the pages they are navigating to aren’t known in the PCL. To solve this I’ve created an interface for every page and set that as navigational target, I don’t know if this will work but I’ll find out soon enough and put it in part 2 if this diary.

Navigational problem solved, on to the next one. Two of my viewmodels could show toast notifications, I use the notifications helper classes from MSDN to get this done but the notification classes aren’t portable (and they really don’t need to be since Windows Phone doesn’t support in-app toasts, the C4F toolkit fixes that luckily) so I created an IMessageAPI interface that has a PopToast() method. In FrameWork.WinRT it shows a build-in toast just like the app used to do.

Hey remember that we have to do everything async now and that we can call the Dispatcher to execute something on the UI thread? Not happening in a PCL… MVVM Light contains a DispatcherHelper that checks if an action needs to be executed on the UI thread and actually executes it there when needed, except in the PCL version. So IDispatcher was born.

With that done I got my project to build again and to run but it’s currently still using the old viewmodels, I expect a whole bunch of new problems when I try to change it to the PCL versions, but that will be for part 2.

What’s next

In part 2 I hope to make the app use the PCL version of the viewmodels and I’ll start working on the Windows Phone project.

Conclusion

PCL projects sound very good in theory but in reality they are a great PITA to work with. Portable HttpClient and portable MVVM Light make them useful but you’ll have to right loads of extra code, abstractions and helper classes to get to something that looks like build once run on two platforms. I could’ve given up and just rebuild everything in a separate solution for WP8 but I want to see how far I can take this and document it along the way.

That said, I have no idea when part 2 will be live, that depends on when I can gather the courage to reference the viewmodel project Smile


Tags:

.Net | Devices | Metro | MVVM Light | PCL | Windows 8 | WinRT | WP8

MSDN webcast: NFC in Windows Phone 8

by Nico

Today I had the pleasure of delivering a webcast for MSDN on near-field-communication in Windows Phone 8. I did have some technical problems, those problems being my phone freezing for the very first time ever, not even able to shut it down. Great timing for something like that to happen, but I think my audience believed me when I told them that the code really works. For those still in doubt, I’ve uploaded the demo project and you can find it here (SkyDrive link).

The slides are available on SlideShare (embedded here) and the recording will soon be available on Channel9

And don’t worry, I do have a new blogpost coming up, I was on holiday last week and very busy this week (webcast, app-a-thons, actual project at work, …)


Tags:

Community | .Net | MSDN | NFC | WP8 | Talk

SQLite in Windows Phone 8: The sequel

by Nico

Read the first part: SQLite with a bit of MVVM Light in Windows Phone 8

Last week I’ve blogged about using SQLite in an MVVM scenario in Windows Phone 8. Since, in my opinion, the post was already getting to an epic length I decided to leave out a part for this week.

I’ll try to keep it a bit shorter this time, should be able to. The part I left out was using relationships and foreign keys with SQLite and the sqlite-net library. I’ll be building upon the project of the previous post, so the task schedule thingy. What we’ll be doing is adding the possibility of creating subtasks so that a task can be divided into smaller tasks. Note that this is just a proof of concept (POC) it’s in no way a complete application and it will have some strange things but that’s the whole fun of a POC.

Let’s kick things off with the creation of a new class for holding the SubTasks.

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

By using attributes we define this class as being a column in the SQLite database and the property Id being a primary key with auto increment. This is all explained in more detail in the previous post. A new attribute here is Indexed on the TaskId property. That attribute states that that property will be an index, it will hold the primary key of the Task table.

Remember that the database was created in the App.xaml.cs? We’ll need to add a line there to create the SubTask table as well. If you haven’t shut down the emulator between the previous post and this one, or you’re testing on an actual device, you’ll need to remove the app so that the database is destroyed or the new table won’t get generated.

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. }
  13.  
  14. private async void CreateDB()
  15. {
  16.     Connection = new SQLiteAsyncConnection("taskDB.db");
  17.  
  18.     await Connection.CreateTableAsync<Task>();
  19.     await Connection.CreateTableAsync<SubTask>();
  20. }

I’ve added the complete snippet as reference, line 19 is the new one.

Next up is the view, this will be quite similar to the Mainpage, a pivot with two pages. One containing a form for adding a new subtask and one containing a list of all subtasks.

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.             <TextBlock Text="Main task ID" TextWrapping="Wrap" />
  13.             <TextBlock Text="{Binding TaskId}" />
  14.  
  15.         </StackPanel>
  16.     </DataTemplate>
  17. </phone:PhoneApplicationPage.Resources>
  18.  
  19.  
  20. <!--  Buttons are defined using the behaviors in the Cimbalino toolkit to allow a bindable appbar  -->
  21. <phone:PhoneApplicationPage.ApplicationBar>
  22.     <shell:ApplicationBar IsMenuEnabled="True" IsVisible="True" />
  23. </phone:PhoneApplicationPage.ApplicationBar>
  24.  
  25.  
  26. <!--  LayoutRoot is the root grid where all page content is placed  -->
  27. <Grid x:Name="LayoutRoot" Background="Transparent">
  28.     <!--  Bindable Appbar buttons  -->
  29.     <i:Interaction.Behaviors>
  30.         <behaviors:ApplicationBarBehavior>
  31.             <behaviors:ApplicationBarIconButton Command="{Binding SaveNewSubTaskCommand,
  32.                                                                     Mode=OneTime}"
  33.                                                 IconUri="/Assets/AppBar/save.png"
  34.                                                 Text="Save Task" />
  35.         </behaviors:ApplicationBarBehavior>
  36.     </i:Interaction.Behaviors>
  37.  
  38.     <Grid.RowDefinitions>
  39.         <RowDefinition Height="Auto" />
  40.         <RowDefinition Height="*" />
  41.     </Grid.RowDefinitions>
  42.     <phone:Pivot Title="SQLite POC" Grid.Row="1">
  43.         <phone:PivotItem x:Name="NewTask"
  44.                             CacheMode="{x:Null}"
  45.                             Header="new subtask">
  46.             <StackPanel>
  47.                 <TextBlock Text="Main task" />
  48.                 <toolkit:ListPicker ItemsSource="{Binding Tasks}" SelectedItem="{Binding SelectedTask, Mode=TwoWay}">
  49.                     <toolkit:ListPicker.ItemTemplate>
  50.                         <DataTemplate>
  51.                             <TextBlock Text="{Binding Title}" />
  52.                         </DataTemplate>
  53.                     </toolkit:ListPicker.ItemTemplate>
  54.                 </toolkit:ListPicker>
  55.                 <TextBlock Text="Title" TextWrapping="Wrap" />
  56.                 <TextBox x:Name="TextBoxTitle"
  57.                             Height="72"
  58.                             Text="{Binding NewSubTask.Title,
  59.                                         Mode=TwoWay}"
  60.                             TextWrapping="Wrap" />
  61.                 <TextBlock Text="Complete by" TextWrapping="Wrap" />
  62.                 <toolkit:DatePicker Value="{Binding NewSubTask.Date, Mode=TwoWay}" />
  63.             </StackPanel>
  64.         </phone:PivotItem>
  65.         <phone:PivotItem x:Name="AllTasks"
  66.                             CacheMode="{x:Null}"
  67.                             Header="all subtasks">
  68.             <phone:LongListSelector ItemTemplate="{StaticResource TaskListItemTemplate}" ItemsSource="{Binding SubTasks}" />
  69.         </phone:PivotItem>
  70.     </phone:Pivot>
  71. </Grid>

The only new thing here is the ListPicker, it’s a control in the Windows Phone Toolkit (get it from NuGet) and it’s kind of like Windows Phone’s version of a combobox. The ItemTemplate is a TextBlock containing the Title of the Task.

If you want details on the bindings, read the previous post. The DataContext for this page binds to a SubTaskViewModel through the ViewModelLocator

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

And here’s the SubTaskViewModel

Code Snippet
  1. public class SubTaskViewModel : ViewModelBase
  2. {
  3.     private readonly IDataService _dataService;
  4.     private readonly INavigationService _navigationService;
  5.  
  6.     private IList<SubTask> _subTasks;
  7.     public IList<SubTask> SubTasks
  8.     {
  9.         get
  10.         {
  11.             return _subTasks;
  12.         }
  13.  
  14.         set
  15.         {
  16.             if (Equals(_subTasks, value))
  17.             {
  18.                 return;
  19.             }
  20.  
  21.             _subTasks = value;
  22.             RaisePropertyChanged(() => SubTasks);
  23.         }
  24.     }
  25.  
  26.     private SubTask _newSubTask;
  27.     private IList<Task> _tasks;
  28.     private Task _selectedTask;
  29.  
  30.     public SubTask NewSubTask
  31.     {
  32.         get
  33.         {
  34.             return _newSubTask;
  35.         }
  36.  
  37.         set
  38.         {
  39.             if (_newSubTask == value)
  40.             {
  41.                 return;
  42.             }
  43.  
  44.             _newSubTask = value;
  45.             RaisePropertyChanged(() => NewSubTask);
  46.         }
  47.     }
  48.  
  49.     public RelayCommand SaveNewSubTaskCommand
  50.     {
  51.         get
  52.         {
  53.             return new RelayCommand(async () =>
  54.                                                 {
  55.                                                     NewSubTask.TaskId = SelectedTask.Id;
  56.                                                     await _dataService.Save(NewSubTask);
  57.                                                     SubTasks.Add(NewSubTask);
  58.                                                     NewSubTask = new SubTask { Date = DateTime.Today };
  59.                                                 });
  60.         }
  61.     }
  62.  
  63.     public IList<Task> Tasks
  64.     {
  65.         get { return _tasks; }
  66.         set
  67.         {
  68.             if (Equals(_tasks, value))
  69.             {
  70.                 return;
  71.             }
  72.  
  73.             _tasks = value;
  74.             RaisePropertyChanged(() => Tasks);
  75.         }
  76.     }
  77.  
  78.     public Model.Task SelectedTask
  79.     {
  80.         get { return _selectedTask; }
  81.         set
  82.         {
  83.             if (Equals(_selectedTask, value))
  84.             {
  85.                 return;
  86.             }
  87.  
  88.             _selectedTask = value;
  89.             RaisePropertyChanged(() => SelectedTask);
  90.         }
  91.     }
  92.  
  93.     public SubTaskViewModel(INavigationService navigationService, IDataService dataService)
  94.     {
  95.         _navigationService = navigationService;
  96.         _dataService = dataService;
  97.         SubTasks = new List<SubTask>();
  98.  
  99.         NewSubTask = new SubTask { Date = DateTime.Today };
  100.         GetData();
  101.     }
  102.  
  103.     private async void GetData()
  104.     {
  105.         Tasks = await _dataService.LoadTasks();
  106.         SubTasks = await _dataService.LoadSubTasks();
  107.     }
  108. }

In this viewmodel we’ll have a list of both the Tasks and the SubTasks because we’ll have to select a Task to attach a SubTask to. The constructor loads in the NavigationService and the DataService from the Ioc container, Tasks and SubTasks get loaded and we’re good to go. Now the navigation isn’t really what it should be in this POC, because you have to go to a Task edit page, click the Add Subtask button and then select the Task you want to create a subtask for, it’s a bit of double work but I don’t care Smile.

Remember the DataService? It’s the class that takes care of all the CRUD operations in our app, it’ll need to do the same for the subtasks. I’m a bit lazy, so I’ve only did the insert and read part. Here’s the read snippet

Code Snippet
  1. public async Task<IList<SubTask>> LoadSubTasks()
  2. {
  3.     return await App.Connection.Table<SubTask>().ToListAsync();
  4. }

Exactly the same as for reading out the Tasks. Now, for saving I altered the SaveTask function to be generic.

Code Snippet
  1. public async Task Save<T>(T newTask)
  2. {
  3.     await App.Connection.InsertAsync(newTask);
  4. }

This function takes in basically anything and saves it in the DB, if you pass something in of a type that doesn’t have a table in the DB the app will crash, hard. So be careful how you use this and you might think of adding some error handling.

And there we are, a working SQLite proof of concept with relationships and everything. Since a picture says more than a thousand words, here are some screenshots.

The Edit Task screen with the Add subtask button

The Add SubTask screen with all the Tasks in a listpicker

List of SubTasks with the Task ID

The entire project can be downloaded in a zip file here (Link to my SkyDrive).


Tags:

.Net | MVVM Light | Metro | WP8 | sqlite

  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