Sharing code between Windows Store and Windows Phone apps.
Presented by Laurent Duveau on February 9th during a Montreal .NET Community special event.
Parts of the presentation were taken from existing Microsoft presentations.
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
Building apps for WP8 and Win8
1. 2013-02-09
Laurent Duveau
Developing for both
Windows Phone 8
and Windows 8
ldex.ca @laurentduveau
Laurent Duveau
Windows 8 Instructor
MVP / MCT / RD
2. Agenda
• Building for Windows Devices
• Consistent Experience
• Tiles, Notifications, Animations
• Differences
• Screen Sizes, Controls, Lifecycle
• Minimizing Development
• Reuse
• Portable Class Library
• Sharing Code
3. Some Key Differences
It’s important to design for the platform differences as well as similarities
Screen Size Controls Lifecycle
Windows Phone Windows Phone Windows Phone
800x480, 1280x720, 1280x768 Panorama, Pivot, ListPicker Launched from start/apps list.
Portrait, Landscape LongListSelector Tombstones apps
Windows Windows Windows
1024x768 GridView, ListView, Semantic Resumes existing apps
Portrait, Landscape, Snapped Zoom, FlipView No tombstoning
4. Strategies for sharing in a XAML app
• Separate UI from app logic (Model-View-ViewModel)
• Share portable .NET code in Portable Class Library
• Use common Windows Runtime API (Add as Link)
• Complete with platform-specific code as necessary
9. Reuse
Reusing pre-built components or libraries
Portable Class Library
• Managed Code
• Reusable library
• One codebase with no conditional compilation
11. Sharing Code
Reusing code by including code files in multiple projects
Share Code Files
•Use Add as Link to include same files in multiple projects
•Change once, Change everywhere
•What to do where platforms don’t match?
•#if conditional blocks
•Inheritance
•Partial Classes and Methods
12. Sharing Code: #if Conditional Blocks
• Enable/Disable lines or chunks of code based on compilation platform
• Existing compilation constants
• NETFX_CORE Windows 8
• WINDOWS_PHONE Windows Phone 8
• Useful for when there are subtle differences in syntax or methods
• Can make code unreadable…
13. Sharing Code: #if Conditional Blocks
#if NETFX_CORE
using Windows.UI.Xaml.Media.Imaging;
#else
using System.Windows.Media.Imaging;
#endif
14. Sharing Code: #if Conditional Blocks
public object Convert(object value, Type targetType, object parameter,
#if !NETFX_CORE
CultureInfo culture
#else
string language
#endif
)
15. Sharing Code: Partial Classes & Methods
• Shared functionality in one code file eg: DataSource.cs
• Platform specific code in additional code file eg: DataSource.WP8.cs
• Classes are marked as partial and compiled into a single class
• Separates platform specific features
• Can use partial methods as a mechanism to separate out platform specific logic
16. Sharing Code: Partial Classes & Methods
/// <summary>
/// DataSource.cs
/// </summary>
public partial class DataSource:IDataSource {
public async Task<IEnumerable<IFolder>> RetrieveFolders(IFolder root) {
... // other logic
var folders = await LoadFolders(root);
... // other logic
return folders
}
}
/// <summary>
/// DataSource.WP8.cs
/// </summary>
public partial class DataSource {
private async Task<IEnumerable<IFolder>> LoadFolders(IFolder root) {
...
}
}
AgendaThe material in this session is broken down into three sections:Building for Windows Devices: This is focused on getting developers to think about the application they’re building. There’s not only a need to consider the common elements (ie tiles, notifications, the use of grids and content rather than chrome) but also to respect the differences (egGridViews and ListViews versus ListPickers and LongListSelectors). We’ll talk about how to deal with different actual screen sizes (Win8 layouts need to scale, WP8 layouts do not (for the most part)). Minimizing Development: This section looks at how to reuse as much code as possible. This can be done by building libraries that can simply be reused using portable class libraryies. Alternatively it may be necessary to simply share code between projects. The latter can allow for high levels of reuse as there are less constraints imposed and gives developers the ability to use partial classes, compiler directives and other techniques for sharing code between projects.Architecture: In the last section of this session there will be discussion around apis for doing common tasks (selecting files, capturing photos etc), some are the same, others vary between platforms. This section will also look at how developers can architect their applications to promote reuse across both platforms, with a heavy focus on the MVVM/Data binding design pattern.
Some Key Differences:Screen SizeRaw screen size. For Windows Phone this isn’t too much of an issue since most applications will scale automatically between the default WVGA (ie 800x480) and the other resolutions available on Windows Phone 8. For Windows you have to design interfaces that can accommodate different screen sizes and aspect ratios. A lot of applications being ported from iPad don’t adapt well to Windows as they’ve been designed for fixed proportions. Use of the GridView and/or ListView controls is essential to ensure interfaces that scale well.2) OrientationOn Windows Phone, apps can optionally support Portrait and Landscape .On Windows: Applications are required to support the Snapped mode. ControlsWindows Phone has unique page level controls such as the Panorama and Pivot which should be used when designing the application. There are also individual controls such as the LongListSelector (recommended to be used in place of the ListBox) and ListPicker (Windows Phone equivalent of a dropdown box) that should be used to be consistent. Windows also brings a number of unique controls:GridView: (groupable) tile array. Also possible to dynamically size items in the grid. The GridView comes with built in styles for input and selectionListView: Replacement for ListBox for displaying list of itemsSemanticZoom: Allows for quick jump through large lists of grid itemsFlipView: Browsing view optimised for touch to pane left-right through sequential items.LifecycleBasic navigation model is relatively similar, as on both the user navigates from one page to another. There is a strong concept of navigating back on both – using the hardware back button on the phone, or via a back button positioned on the upper a[[ bar on Windows 8.However, there are differences in the way applications are launched or resumed that developers have to be aware of and must code for. These differences include: - Windows Phone applications are always (re)launched when started from the start screen or the applications list (although this default behaviour can be overridden in WP8 if Fast Application Resume is implemented). Windows applications are simply resumed (no navigation events in/out of page). - Windows Phone applications can be tombstoned, unlike Windows applications which are suspended but never tombstoned. - Both platforms support a variety of different entry points Windows Phone: normal startup, toast & tile launch, Speech launch, App Connect (ie search), protocol and file association Windows: normal startup, toast & tile launch, Search, Share, protocol and file association
Minimizing DevelopmentSince in theory Windows Phone is the same core platform as Windows there should be a common development strategy that can be applied. Unfortunately this is one quite the case – this section looks at some of the pitfalls and how they can be overcome.
ReuseThe supported scenarios for complete reuse are very limited. It’s not possible to build a single executable that will simply run across both platforms (unlike iOS or Android where you can effectively build universal applications which will run on both devices). It’s also not possible to simply reuse components built for one platform on the other. The only true reuse scenario that is currently supported is via a Portable Class Library:Portable Class LibraryThese are class libraries that contain only managed code and as such can be simply referenced by managed applications for both Windows and Windows Phone. This takes a lowest common denominator approach resulting in a very constrained sub-set of even the Windows Phone .NET framework.Pros: Written in managed code, complete reuse with the ability to simply “Add Reference” to the built assembly.Cons: Severe limitations imposed by the need to work across different platforms without targeting. Important features such as INotifyPropertyChanged and Task are missing making it difficult to use in practice.
For demonstration notes please look in the “Demonstration” folder and open the corresponding Word document.
Sharing CodePortable Class Libraries are quite limiting so often alternative approaches must be adopted.An alternative is to share the actual code files between projects for different platforms. Whilst this would appear to add an overhead the result is that Visual Studio is able to maintain links to files even if they aren’t in the one project structure. This means that you can have multiple projects all referencing the same source code files. This means that when you update the source file it will be updated across all projects that reference it.Sharing code files works well for where there are common apis across the different platforms. However it would appear to breakdown where there are differences in the APIs, or even just the syntax of APIs, between the platforms. Simply sharing code files may generate compilation errors when code is added that is specific to only one of the platforms. In this section three methods for combating this will be presented#if Conditional Blocks where compilation symbols are used to effectively comment out blocks of codeInheritance where platform specific subclasses are generated to expose additional properties/methodsPartial Classes and Methods where platform specific methods can be grouped together rather than being dispersed through the shared code
#if Conditional BlocksThis is the simplest form of logic that can be used to separate platform specific code. Both Windows and Windows Phone already has platform specific build constants defined, being NETFX_CORE and WINDOWS_PHONE respectively. These can be used to comment out, or enable blocks of code at compile time.This strategy is useful for where there are subtle differences (for example a different namespace or slightly different parameters to a method).The biggest issue with this strategy is that it can quite easily make code unreadable and hard to maintain. For example in the case where an #if statement was used to switch between two platform specific implementations it would be hard to follow the logic as the developer would have to continually jump over blocks of code relevant to the other platform. This extends into the debugging experience making it harder to track down issues.
Example 1: Using #if conditional blocks to switch between two similar namespaces. In this case the code was referencing the BitmapImage class which is in a different namespace on each platform (see PhotoManager.Core.WP8/Data/Entities/Picture.cs for example)
Example 2: Using #if conditional block within the signature for a method. This is an example of how the inappropriate use of #if can lead to hard to read code (for an implementation of IValueConverter – see PhotoManager.WP8/Converters/BoolVisibilityConverter.cs). One approach here to make this easier to read would be to simply repeat the whole method signature within the two #ifdef alternatives, rather than trying to split at the point of difference.
Partial Classes & MethodsAnother technique is to use partial classes.Partial classes came about back in the days of Windows Forms where developers wanted to be able to add logic to a form but didn’t want to modify the designer generated file. By putting their additional logic in a separate file and marking the classes as partial, all the code would end up being compiled down into a single class. This strategy is great for separating out platform specific implementations: the shared logic can reside in the primary file (egDataSource.cs); platform specific logic can reside in files created for the specific platform (eg DataSource.WP8.cs and DataSource.Win8.cs). This has the added benefit in that only the code that is relevant to the specific platform is included in the project (ie DataSource.Win8.cs wouldn’t be included in the WP8 project and vice versa).It’s possible to use partial methods to call from code in the primary file into the platform specific code – if the platform specific code doesn’t “implement” the partial method it’s simply compiled out and never called. To enforce platform specific implementation simply call the required method from the primary file – this will yield a build error until the platform specific method is created.Pro: All the methods appear within the same class (and as such in the methods dropdown in Visual Studio).Con: Again you end up with multiple files for the same class
ExampleHere we see the primary file, DataSource.cs (PhotoManager.Core.WP8/Data/DataSource.cs), with a method called RetrieveFolders that does a bunch of work before and after calling LoadFolders. LoadFolders exists only in the platform specific files, in this case DataSource.WP8.cs (PhotoManager.Core.WP8/Data/DataSource.WP8.cs).Note that in this case a platform specific suffix has been used – this is similar to what you see with XAML (mypage.xaml) and the corresponding code-behind file (mypage.xaml.cs).Example 3: Open PhotoManager.Core.WP8/Data/DataSource.csOpen PhotoManager.Core.WP8/Data/DataSource.WP8.csIllustrate how the WP8 specific logic resides in separate files, yet all methods are accessible via methods dropdown.
For demonstration notes please look in the “Demonstration” folder and open the corresponding Word document.If you have demoed the code sharing techniques as you went through the preceding slides, you may want to hide this demo slide.