Rico Suter's blog.
 


This post shows how to develop an app which targets the WP7 and WP8 platform at the same time. The idea is to create two projects - one for WP7 and one for WP8 - and link all files into one of the projects. This way you don’t have to maintain the code twice and only have to develop in one project. On Microsofts website you can find the base idea. However this article shows even more problems and their solutions when using this approach. Here are the steps to setup the solution:

1. Create the Visual Studio solution

Create a new solution with a WP7 and WP8 project. The following listing shows the directory structure of the solution:

  • MyProject/
  • MyProject/MyProject.sln
  • MyProject/MyProject.Wp7/MyProject.Wp7.csproj
  • MyProject/MyProject.Wp8/MyProject.Wp8.csproj

2. Add compiler flags

Add compiler flags “WP7” and “WP8” to each of the projects to later use in the shared and linked code like this:

#if WP8
...
#else
...
#endif

This is necessary as some of the APIs are different or are missing on one of the two targeted frameworks. Using these compiler flags it is also possible to exclude some features or add performance optimizations for the WP7 app.

3. Add pre-build script for non-linkable files

Edit your “MyProject.Wp7” project’s properties (right-click on the projects and select “Properties”) and add the following pre-build script in the “Build Events” settings:

copy $(SolutionDir)MyProject.Wp8\Background.png $(SolutionDir)\MyProject.Wp7\Background.png
copy $(SolutionDir)MyProject.Wp8\ApplicationIcon.png $(SolutionDir)\MyProject.Wp7\ApplicationIcon.png
copy $(SolutionDir)MyProject.Wp8\SplashScreenImage.screen-WVGA.jpg $(SolutionDir)\MyProject.Wp7\SplashScreenImage.jpg

This is needed because these three files must be directly available in the project and can therefore not be linked. Using this script, they are copied from the parent WP8 project before each build. After setting the pre-build script, build the project “MyProject.Wp7” (which runs the script) and include the copied three files into the project “MyProject.Wp7”. This script requires that you have three SplashScreenImages in your WP8 project (which is recommended):

  • MyProject/MyProject.Wp8/ SplashScreenImage.screen-WVGA.jpg: 480*800
  • MyProject/MyProject.Wp8/ SplashScreenImage.screen-WXGA.jpg: 768*1280
  • MyProject/MyProject.Wp8/ SplashScreenImage.screen-720p.jpg: 720*1280

4. Same namespaces for both projects

It is important to use the same namespaces and assembly names in both probjects! Otherwise you will have problems with resource files because they are automatically using the base namespace from the project. If you don’t use the same namespaces the project cannot be compiled or the application crashes because the resources cannot be found because they are expected in another namespace (throws a MissingManifestResourceException).

Develop always in the WP8 project (the parent project) and add all files from “MyProject/MyProject.Wp8” into “MyProject.Wp7” as links in the same location (right-click on directory, then “Add/Existing Item…”, then “Add As Link”). Sometimes depended files like *.xaml.cs are not correctly added (not dependent). You can fix this problem by editing the .csproj file or by using the VSCommand Visual Studio extension (select both files and run “Group items”).

6. Add Microsoft.Bcl.Async to use async/await in WP7

Add the NuGet package Microsoft.Bcl.Async to your project to enable the async/await programming model for WP7 too. This way you can use this nice feature on both platforms.

7. Use wrapper classes for classes with different DLL locations

Some classes (mostly user controls) are located in different DLLs when targeting WP7 and WP8 respectively. In these cases you have to implement a wrapper class and use the wrapper class in your XAML. This way the XAML code can be used to target WP7 and WP8 at the same time. Two examples are the ProgressBar and Panorama controls. Implementations of wrapper classes for these two controls can be found in the MyToolkit.Extended library (in MyToolkit.UI namepace). The following shows the wrapper class for the ProgressBar control.

#if WP8
    // implementation from OS Framework
    public class MyPerformanceProgressBar : ProgressBar { } 
#else
    // implementation from Windows Phone Toolkit
    public class MyPerformanceProgressBar : Microsoft.Phone.Controls.PerformanceProgressBar { } 
#endif

Warning: Don’t use the PerformanceProgressBar implementation from the Windows Phone Toolkit for Windows Phone 8: It is available but not working properly (it is invisible)! Instead use the wrapper class above.

8. When targeting WinRT, use common HTTP library

It is possible to use the described approach to even reuse code for a Windows 8 app (usually only view models and domain logic, no XAML code or other user interface code). If you are using HTTP you will have the problem that the HttpClient class from the WinRT framework is missing in the Windows Phone framework and your view models that use this class cannot be shared (linked). Here you have two options: You can install the NuGet package Microsoft.Net.Http which brings this class to Windows Phone or use the HTTP classes from MyToolkit which additionally support GZIP, file upload and other useful features (NuGet: MyToolkit).



Discussion