Introduction
Not so long ago Microsoft announced the release of an update to Windows Phone 7, codenamed Mango, which brings a number of new features. There will be substantial differences between the old (WP7.0) phones and the Mango (WP7.1) phones. While the Mango developer tools are freely available, the first real devices should appear within a few weeks.
As for every OS update the developers have to solve a number of questions ranging from the migration to the new technology through the simultaneous development for different platforms up to the efficient use of the new capabilities.
Windows Phone 7 is one of the Resco's core platforms and we offer there a control library — Resco MobileForms Toolkit, Windows Phone Edition (Resco.Controls). Our users started asking if the library is Mango-compatible. In two cases I got even signals that AdvancedList control might have problems.
Ok, as the developer interest in Mango clearly growths, we had no choice but to join. Below I'll be talking about the experience I had when migrating to Mango, more specifically to its Beta 2 release.
Note that I won't be talking about Mango features, but rather about the problems I encountered. I'll also try to look behind the scenes so that the readers better understand how the Mango update is implemented.
Breaking changes in Mango acc. to Microsoft
The official list of breaking changes between WP7.0 and WP7.1 can be found in the WP SDK 7.1 Release Notes and can be downloaded from here. The list contains a number of very specific points that should not affect most developers.
However, several changes might potentially impact existing code, for example:
- In WP7.1 “Image decoding happens on a background thread by default, instead of on the UI thread.“ As discussed here, the background decoding can break existing code. (For example you cannot use image dimensions right after calling BitmpaImage.SetSource; instead you have to wait for ImageOpened event.) Microsoft might revert this change in the final SDK release.
- While in WP7.0 the WebClient response was always received on the UI thread, in WP7.1 the response is received on the thread that created the request. The developers, who rely on the original behavior and (for example) directly update the UI as part of the response processing, will experience crashes. The problem is discussed here.
- WP7.1 comes with improved ListBox scrolling. The cost for this improvement is a) Delayed update of the ScrollViewer properties; b) ScrollViewer Manipulation Delta events are suppressed. For workarounds see here.
Other potential incompatibilities or behavioral changes are reported here.
So far the theoretical preparation — I concluded that the migration to Mango should hardly present any risk.
Installation of the Mango support
Of course, we have to start with the installation, which encompasses
- Visual Studio 2010 SP1 (if you haven't done it already — see the Visual Studio About dialog)
- Windows Phone SDK 7.1 (Beta 2)
Installation was long (due to web downloads), but straightforward.
When done, I opened an existing project and looked around what has changed.
Seemingly nothing, but when I looked into the project properties I found new option — Target Windows Phone version that lets you select either WP7.0 or WP7.1. Ok, that seems to be the thing that should be tested first.
Figure 1 — Project preferences let you select phone version
Testing existing projects
I tested altogether 8 non-trivial apps, i.e. all basic Silverlight controls as well as all custom controls from Resco.Controls
library. The code used a lot of binding and templating, dynamic control construction, animations etc. Perhaps the only important controls not tested were Pivot
and Panorama
— maybe next time.
Every project was tested in two steps:
- Simple recompilation of the unchanged old project and running it on the a) WP7.0 device, b) WP7.1 emulator.
- Modifying the project to target WP7.1 and testing it on the WP7.1 emulator.
Well, I denote the emulator as WP7.1, but this just means the emulator left after the installation. It looks like Mango emulator, but that's all I can say right now.
Testing Results
I have to say it was better than expected: One minor problem and another serious one.
The first problem was this build error:
"MSBUILD : error : Xap packaging failed. Could not find file '...ApplicationIcon.png'."
It turned out that I moved the png file to the Images subfolder, but did not update the WMAppManifest.xml file. Mango was less tolerant than the old SDK; in fact it correctly reported an existing bug.
The second problem was a lot worse. I used a ListBox
-based class with custom ListBoxItem
. It appeared to crash in the layout phase with a nonsense error. (Non-specific error with zero information attached.) Simply a situation where you don't know what to do.
After poking around and classifying all available info as useless I decided for brute-force attack: Simplify, simplify, simplify...
It might have taken a dozen of iterations and elimination of 95% of the code until I found that Mango does not like this construction (used within ListBoxItem template):
<ControlTemplate>
<ContentPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
Once I realized that ContentPresenter implicitly binds Content if used within the ControlTemplate, I removed TemplateBinding and everything worked (even in WP7.0 case):
<ControlTemplate>
<ContentPresenter/>
</ControlTemplate>
(The template is a bit simplified, but you get the idea.)
Figure 2 — Resco AdvancedList using problematic item template
New compiler
Just for curiosity: Let's look first at the influence of the new compiler. Strictly speaking this is not the result of the Mango update, but if you did not install VS SP1 (my case), Mango requires it.
I took an existing project, saved its output (i.e. a dll file) and recompiled it to get the new dll.
Binary comparison of the old/new output dll's shows too many differences, but I have a strong feeling that substantial part of them are simple code shifts.
I opened both old and new dll in the Reflector
, extracted the sources (remarkably readable, BTW) and compared them. Result: Sources are basically identical. The only difference was a formal one — ordering of TemplatePartAttribute's
in the class declarations.
As expected, compiler changes (hopefully) won't play any role.
What was installed actually?
Back to Mango. Let's look at the files installed on the computer.
The emulator resides in
C:\Program Files (x86)\Microsoft XDE
and was apparently overwritten by 7.1 SDK. (An irreversible change.)
Old phone assemblies are located in the folder
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone.
This folder contains copy of all system assemblies installed on the pre-Mango phones. It was here since ages and its content was apparently not affected by new SDK installation. Instead, Mango phone assemblies were copied side-by-side to a new folder
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone71
It looks like both 7.0 and 7.1 environments are available and the tools such as the emulator can decide which one to use. For the time being this is a hypothesis, but we shall prove it later.
Figure 3 — Left: WP7.0 system assemblies, Right: WP7.1 (xml files are omitted)
Several things are worth noting:
- WP7.1 contains several new assemblies (system.data.linq, mscorlib.extensions, several XNA assemblies). If you want to know what they contain, open them in Reflector or read Mango documentation.
- Most of the old WP7 assemblies have changed.
- Changed assemblies preserve old versions.
Well, in the old good days we learned that versions are here to remove the so-called dll hell as they provide unique identification. Apparently the reality combining independent platforms (Silverlight, .NET, phone) is too complex to rely on the versioning info.
Anyway, theoretical possibility that my future app using Mango-specific system classes would be run on WP7.0 phone worries me a bit.
New Concept — Profile
Well, the word "new" is not quite justified. The concept was here before the Mango was introduced. It just wasn't emphasized since only a single profile existed there.
Microsoft uses the word Profile to denote Target Windows Phone version. There are 2 profiles at present:
- WindowsPhone
- WindowsPhone71
You can easily verify above statement: Open a dll file in a binary viewer and look for the string Profile.
- Old assemblies (dll files) contain the string
Profile=WindowsPhone
.
- As you probably guess, the assemblies built for Mango use the string
Profile=WindowsPhone71
.
Should this be the key concept that prevents the conflicts mentioned above?
What's the difference between WP7.0 and WP7.1 projects?
As already mentioned the project properties offer the target selection. However, the things are not that simple: Old projects can be upgraded to WP7.1, but once you do that, Visual Studio does not let you downgrade the project back to WP7.0. (The corresponding option gets lost.)
On the other hand, it is not difficult to bypass this limitation. Here is how you can downgrade WindowsPhone71 project to 7.0:
TargetFrameworkProfile: Substitute WindowsPhone71
for WindowsPhone
- In the WMAppManifest.xml:
AppPlatformVersion: Substitute 7.1 for 7.0
Remove capabilities ID_CAP_ISV_CAMERA, ID_CAP_CONTACTS, ID_CAP_APPOINTMENTS
- In the project references:
Remove reference to mscorlib.extensions
.
How to create an installer for a Control Library
The problem: We have a controls library developed for old WP7, i.e. it does not refer to Mango-specific functionality.
- Can we offer this library for Mango phones?
- If so, do we have to recompile it with new Mango SDK? Which target to select? (7.0 or 7.1) Do we need to offer two binaries — one for each target?
Of course, the ideal solution would be to use a single binary. Let's look for it.
Google and stackoverflow.com did not yield any help, I was left on my own.
As usual I started with experiments. I created 2 versions of Resco.Controls.dll — one targeting WP7.0 and the other one for WP7.1. I tried to use these dll’s in differently targeted projects.
Note that there are several ways how you can use a control library in your application project:
-
Installed library is offered if it matches the project type
In case of WP7.0 the installation means that the folder where the library dll file resides is written in the Registry key:
HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Silverlight for Phone\v4.0\AssemblyFoldersEx.
Libraries installed this way are offered in Add References dialog .NET tab providing that their target (profile) matches the project target. In other words WP7.0 libraries are offered for WP7.0 projects and WP7.1 libraries for WP7.1 projects.
-
By browsing you can add downwards compatible library
If you use Add References dialog Browse tab, you can select any library dll file. You can thus add a reference to a compatible library (as above), but also a reference from a WP7.1 project to a WP7.0 library.
However, you can't refer WP7.1 library from a WP7.0 project. (You get the error "A reference to a higher version or incompatible assembly cannot be added to the project.")
-
By hacking the xap file you can add any library
Xap file is the final product of your project that serves as the application installer. It is a zip file and as such you can browse its content. (Do it, it is rather instructive. You will find here both your application dll, but also the library dll.)
Surprisingly, you can modify the Xap file by placing there another version of the control library. This bypasses any compatibility checks as you can this way install WP7.0 application using WP7.1 library.
I did this on my developer unlocked WP7.0 device, where I successfully launched a WP7.0 application using Resco.Control library built for WP7.1 target. Maybe the Marketplace will use stronger security checks to prevent such tricks.
Figure 4 — Content of the xap file
Interesting results, but they did not answer the original question.
I decided for the last trial — to install the Mango release of the Silverlight for Windows Phone Toolkit from Microsoft and analyze the Registry changes.
WP7.1 libraries appear to be registered at
HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Silverlight for WindowsPhone\v4.0\AssemblyFoldersEx
Knowing above, I created new library installer that used WP7.0 library and registered it in both Registry folders mentioned above.
This was it — the single binary serving all kinds of projects. (I.e. the library that can be added from Add References dialog .NET tab to both WP7.0 and WP7.1 projects.)
Figure 5 — Registration info for Resco.Controls assembly
Coexistence of WP7.0 and WP7.1 in Visual Studio and Emulator
Above I formulated a hypothesis that the Mango emulator reads the application profile and decides whether to use WP7.0 or WP7.1 libraries. Below I'll give a proof for this statement. I'll even show that the Visual Studio does the same when compiling a project.
Let’s go step by step and start with the description of the test application that served as a laboratory.
One day I noticed that Mango apps use different numerical keyboard. This caught my attention and I coded an app that tests all possible keyboards. Let’s start by explaining what the app does.
|
|
Figure 6 — TextBox with numeric keyboard, WP7.0
|
Figure 7 — The same TextBox for WP7.1
|
Writing the Test Application
The keyboard is typically defined in Xaml such as for example
<TextBox InputScope="Number"/>.
The XAML syntax is simple and intuitive, yet it is not suited for my purposes — I wanted to find ALL differences in the keyboard treatment. The C# equivalent of the above Xaml code is here:
var scopeName = new InputScopeName() { NameValue = InputScopeNameValue.Number };
var keyboard = new InputScope();
keyboard.Names.Add( scopeName );
TextBox box = new TextBox() { InputScope = keyboard };
(If you ask why XAML is so much simpler, then it uses InputScopeNameConverter
that does the hard work by constructing InputScope
from a string.)
The enumeration InputScopeNameValue
contains all possible keyboard types. Apparently, the solution would be to construct one TextBox
for every possible keyboard, i.e. every InputScopeNameValue
member.
The problem was that InputScopeNameValue
is a long enum
and I was a bit lazy. Moreover, I was not sure if the enum
definition did not change in Mango. (Well, at this point I theoretically admitted this, but could not imagine how this would be done.)
I decided to enumerate InputScopeNameValue
values by code. .NET offers nice method for this — Enum.GetValues
. Unfortunately, this method is stripped off from Silverlight libraries.
No problem, this code does the job:
public static IEnumerable GetEnumValues(Type enumeration)
{
IList<object> enums = new Collection<object>();
if (enumeration.IsEnum)
{
foreach (FieldInfo fieldInfo in
enumeration.GetFields(BindingFlags.Static | BindingFlags.Public))
enums.Add((Enum)fieldInfo.GetValue(enumeration));
}
return enums;
}
The rest was straightforward — I created one TextBox
for each keyboard type and added it to a grid together with a label (a TextBlock
) describing the keyboard used. Here is the code:
foreach (InputScopeNameValue scope in GetEnumValues(typeof(InputScopeNameValue)))
{
TextBlock txt = new TextBlock() { Text=scope.ToString(), FontSize=15 };
var keyboard = new InputScope();
var scopeName = new InputScopeName() {NameValue = scope};
keyboard.Names.Add( scopeName );
TextBox box = new TextBox() {InputScope = keyboard};
}
So we have an app that can enumerate all keyboards and apply each one to its own TextBox
. Let’s test it. I ran the app for the first time and got an immediate crash.
Ok, let’s look what the debugger says ... it showed a crash in InputScopeName
constructor. Because the code is correct, the only explanation is that some InputScopeNameValue
's are illegal.
Surprise, surprise... msdn says the opposite. But ok, I added try/catch around the InputScopeName
construction and — in case of an exception — filled the TextBox with the text Unsupported
. Next figure shows the result.
Figure 8 — App testing all InputScopeNameValues
So I had a working WP7.0 app where I could test each and every keyboard. As next, I created an identical project and targeted it to WP7.1.
Finally, I could start comparing WP7.0 vs. WP7.1.
Supported keyboards on both platforms
Both WP7.0 and WP7.1 show the same unsupported keyboards. You see all of them in the above picture; the rest (more than 50 keyboards) work well.
WP7.1 offers two new keyboards — NumericPassword
and Formula
. You won't find them in msdn, but if you open InputScopeNameValue
from metadata (context menu for InputScopeNameValue
, then select Go To Definition), you will see this comment: "Do not use".
Further, after opening all TextBoxes
, it seems (I wouldn't swear at it) that the only keyboards with different visual appearance are those with numeric character. (DateDay
, DateMonth
, DateYear
, TimeHour
, TimeMinorSec
...)
What can be read from metadata
Above I explained how to get InputScopeNameValue
definition from metadata. If you do the same in both projects, you can compare WP7.0/WP7.1 definitions of the enum. Here is a part of the WP7.0 code:
using System;
namespace System.Windows.Input
{
public enum InputScopeNameValue
{
EnumString = -5,
Xml = -4,
……………………………………………………………
Maps = 55,
ApplicationEnd = 55,
}
}
WP7.1 code is very similar. The only difference in the enum definition is the two added scopes mentioned above — NumericPassword
and Formula
. Except that there is just one subtle difference that I would overlook if both enums
were not opened in a diff tool. It is the header line which reads
The comment points to the assembly dll file that was used to generate displayed enum
definition. (Compare to the chapter, where I listed the folders where the phone dll’s are installed.) Part of the generated code – namely the comments – was taken from System.Windows.xml
file that accompanies the dll file. This file serves as the data source for Visual Studio context help and intellisense.
See the implication?
- Visual Studio links different phone dll’s depending on the project target.
- Visual Studio context help depends on the project target as well.
Running simultaneously WP7.0/WP7.1 apps on the emulator
While testing both keyboard apps they got simultaneously installed on the Mango emulator.
Now, when you run the WP7.0 app, it shows WP7.0 keyboards. And vice versa — WP7.1 app shows WP7.1 keyboards. On the same emulator!
For me this proves that the emulator behaves like Visual Studio — it looks at the app target (profile) and links dynamically to respective .Net assemblies.
Not that I would be surprised (I expected that), yet it pleases when your hypothesis gets confirmed.
Summary
Code compatibility:
- The old WP7.0 code should work with Mango phones, although occasional incompatibilities are not excluded.
- Acc. to the official documentation there are just a few breaking changes that should not impact vast majority of the developers.
- Some API changes are not even reported by Microsoft as they are considered fully safe. Example of such a change is the extension of the InputScopeNameValue enum.
System phone assemblies:
- During the installation of the Mango developer tools the phone OS assemblies (Microsoft.Phone.dll etc.) for both WP platforms are copied side by side into different folders on your developer machine.
- Documentation xml files (Microsoft.Phone.xml etc.) are copied to the same folders.
- WP7.1 contains all WP7.0 assemblies. Most of them are unchanged, although a few got updated.
- WP7.1 contains a number of new assemblies, i.e. the number of API’s that the developer can use substantially increased.
- WP7.1 assemblies have the same version as WP7.0 assemblies. This version refers to the Silverlight and cannot be thus used to differentiate the phone target.
Visual Studio:
- VS lets you select the project target — WP7.0 or WP7.1.
- Depending on the target the VS selects proper phone assemblies. These assemblies are then used for several purposes such as the help system, compilation etc.
- Project output (application, control library) contains the information about the target, for which it was built. This information takes the form of a profile string and can have two values — WindowsPhone or WindowsPhone71.
Emulator:
- You can install WP7.0 and WP7.1 apps side by side on the same emulator instance.
- When an application is launched, the Mango emulator reads its profile and dynamically links to respective phone assemblies.
- This way the emulator can properly model both a WP7.0 and a WP7.1 device.
Control libraries:
- The control library contains the profile string similarly to ordinary applications. We can thus differentiate between WP7.0 and WP7.1 libraries.
- When developing an application, you can add reference to a compatible library. The only illegal combination: You cannot refer WP7.1 library from a WP7.0 project.
- If your control library is WP7.0 compatible, you can distribute a single (WP7.0) binary. During the installation the library should be registered as both WP7.0- and WP7.1-compatible.
About the Author
Jan Slodicka. Programming for over 30 years. Covered several desktop platforms and programming languages. Since 2003 working for Resco on mobile technologies – Palm OS, Windows Mobile, Windows Phone 7, Android.
You can contact me at jano at resco.net or through Resco forums.
Resco MobileForms Toolkit — Windows Phone 7 Edition can be downloaded from http://www.resco.net/developer/mobileformstoolkit. The Toolkit contains a set of useful controls that simplify Windows Phone 7 programming. Besides WP7, there is also Windows Mobile, Android and iOS edition.
Resco is a company with a long tradition of mobile programming covering many platforms and both end-user applications and developer tools.