WP to W8: API Mapping
|
This article is part of a series about my experience porting apps from Windows Phone to Windows 8. Official porting guidance can be found here and don’t forget to follow the Building Windows 8 blog and the Windows 8 App Developer blog for the latest information. |
This article will be what my co-worker and friend Ryan Lowdermilk likes to refer to as a “SEO piece”. What Ryan means is while it may not make for easy chair reading, it will still meet a need for those searching for a particular piece of information. The information in this article is how commonly used Windows Phone APIs and XAML features map (or do not map) to their Windows 8 counterparts.
There won’t be a lot of dialog in this article. I’ll mention what the API is used for, show the Windows Phone version and show the Windows 8 version. If there are any important tricks to note, I’ll list those too.
XAML Namespaces
As mentioned in the first post, namespaces are declared differently
WP – xmlns:imgsch="clr-namespace:ImageSearch;assembly=…"
W8 – xmlns:imgsch="using:ImageSearch"
We change clr-namespace: for using: and we no longer have to specify the assembly name. This is nice because the namespace is resolved across assemblies, so we don’t have to have multiple namespace declaration if the same namespace is used in multiple dlls.
XAML Constants
Native Types (string, int) are in a different namespace:
WP – <sys:String x:Key="AppName">Foo</sys:String>
W8 – <x:String x:Key="AppName">Foo</x:String>
These kinds of constants are rarely used in Xaml, but they do come in handy for reusable strings like the application name. Just be aware that in Windows 8 you use the x: prefix for these types.
Touch Input
Windows 8 has a unified input system and no longer supports mouse-specific events:
WP – MouseLeftButtonUp="eventhandler"
W8 – PointerReleased="eventhandler"
The eventhandler above would get called whenever the user releases the right mouse button, raises their finger off the display or removes the pen from the surface. All three input devices are considered “pointers” and each “pointer” can be tracked individually if desired.
Even better, consider using the new gesture and Item events:
W8 – Tapped="eventhandler"
W8 – ItemClick="eventhandler"
Note: Don’t forget IsItemClickEnabled="True"
The Item events like ItemClick are especially valuable because you know that a) an item was actually tapped and b) which item it was. This is so much better than trying to use the SelectionChanged event or LeftMouseButtonUp and checking the SelectedItem property.
Event Handler Changes
RoutedEventArgs is still used for most control events like button click. However, RoutedEventArgs is now in a different namespace (and you’ll have to change it in your code behind):
WP – System.Windows.RoutedEventArgs
W8 – Windows.UI.Xaml.RoutedEventArgs
Since mouse events are gone,MouseButtonEventArgs is too. Mouse events are traded for gesture or pointer events:
WP – System.Windows.Input.MouseButtonEventArgs
W8 – Windows.UI.Xaml.Input.TappedRoutedEventArgs
W8 – Windows.UI.Xaml.Input.PointerRoutedEventArgs
Navigation
On Windows Phone we navigate to a Uri and we pass any parameters as part of the query string. On Windows 8 we navigate to the Type of the page and parameters can be passed as whole objects.
| Windows Phone 7 |
|
NavigationService.Navigate(new Uri("/DetailsPage.xaml?Id=5", UriKind.Relative)); |
| Windows 8 |
|
Frame.Navigate(typeof(DetailsPage), e.ClickedItem); |
Storing Settings – Local
Both Windows Phone and Windows 8 provide a way to store application settings between runs on the same device.
| Windows Phone 7 |
|
settings = IsolatedStorageSettings.ApplicationSettings; settings["exampleSetting"] = "Hello Phone"; |
| Windows 8 |
|
settings = ApplicationData.Current.LocalSettings;
container = settings.CreateContainer(“main", ApplicationDataCreateDisposition.Always); settings.Containers["main"].Values["exampleSetting"] = "Hello Windows"; |
Storing Settings – Roaming
Windows 8 provide a way to store application settings that will get synchronized across the users devices. For more information see Guidelines for roaming application data.
| Windows Phone 7 |
|
Not an option |
| Windows 8 |
|
settings = ApplicationData.Current.RoamingSettings;
// The rest is the same as local settings |
Storing Files – Local
Both Windows Phone and Windows 8 provide a way to store files that belong to the application.
| Windows Phone 7 |
|
using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { store.CreateDirectory("SampleDirectory"); rootFile = store.CreateFile("SampleFile.txt"); // Open stream rootFile.Close(); // Stream must be closed } |
| Windows 8 |
|
folder = ApplicationData.Current.LocalFolder;
// This is a StorageFile. It is not open. file = await folder.CreateFileAsync("SampleFile.txt", CreateCollisionOption.ReplaceExisting);
// Writes text and closes file in one line await FileIO.WriteTextAsync(file, "Hello World"); |
Storing Files – Roaming
Windows 8 provide a folder for files that will automatically get synchronized across the users devices. For more information see Guidelines for roaming application data.
| Windows Phone 7 |
|
Not an option |
| Windows 8 |
|
folder = ApplicationData.Current.RoamingFolder; // The rest is the same as a local file |
Storing Files – Temporary
Windows 8 provide a folder for files that will automatically get deleted by the system maintenance task.
| Windows Phone 7 |
|
Not an option |
| Windows 8 |
|
folder = ApplicationData.Current.TemporaryFolder;
// The rest is the same as a local file |
Creating a Secondary Tile
Both Windows Phone and Windows 8 offer secondary tiles, but they are created and updated in different ways.
| Windows Phone 7 |
|
tileData = new StandardTileData { // Set tile data } ShellTile.Create(new Uri("/ItemDetail.xaml?Id=123", UriKind.Relative), tileData); |
| Windows 8 |
|
tile = new SecondaryTile( tileId, // Tile ID shortTitle, // Tile short name title, // Tile display name "Id=123", // Activation argument TileOptions.ShowNameOnLogo, // Tile options "ms-appx:///images/someImage.png" // Tile logo ); tile.RequestCreateAsync(); |
Updating the Primary Tile
Important: On Windows 8, tiles are created using XML instead of classes. Microsoft has created helper classes to work with tiles as objects instead of XML. These helper classes are included in the App tiles and badges sample. The Windows 8 code below leverages these helper classes.
| Windows Phone 7 |
|
tile = ShellTile.ActiveTiles.First(); if (tile != null) { tileData = new StandardTileData { // Set tile data } tile.Update(tileData); } |
| Windows 8 |
|
wide = TileContentFactory.CreateTileWideImageAndText01(); square = TileContentFactory.CreateTileSquareImage(); wide.SquareContent = squareContent;
// Set wide and square tile data wide.TextCaptionWrap.Text = "This tile uses images"; wide.Image.Src = "ms-appx:///images/redWide.png"; square.Image.Src = "ms-appx:///images/graySquare.png";
// Update TileUpdateManager.CreateTileUpdaterForApplication().Update(wide.CreateNotification()); |
Updating the Secondary Tile
Important: On Windows 8, tiles are created using XML instead of classes. Microsoft has created helper classes to work with tiles as objects instead of XML. These helper classes are included in the App tiles and badges sample. The Windows 8 code below leverages these helper classes.
| Windows Phone 7 |
|
tile = ShellTile.ActiveTiles.FirstOrDefault(<LINQ Query>); if (tile != null) { tileData = new StandardTileData { // Set tile data } tile.Update(tileData); } |
| Windows 8 |
|
wide = TileContentFactory.CreateTileWideImageAndText01(); square = TileContentFactory.CreateTileSquareImage(); wide.SquareContent = squareContent;
// Set wide and square tile data wide.TextCaptionWrap.Text = "This tile uses images"; wide.Image.Src = "ms-appx:///images/redWide.png"; square.Image.Src = "ms-appx:///images/graySquare.png";
// Update TileUpdateManager.CreateTileUpdaterForSecondaryTile(tileId).Update(wide.CreateNotification()); |
Toasts
Important: On Windows 8, toasts are created using XML instead of classes. Microsoft has created helper classes to work with toasts as objects instead of XML. These helper classes are included in the Toast notifications sample. The Windows 8 code below leverages these helper classes.
| Windows Phone 7 |
|
var toast = new ShellToast toast.Show(); |
| Windows 8 |
|
toast = ToastContentFactory.CreateToastImageAndText02(); toast.TextHeading.Text = "Heading text"; toast.TextBodyWrap.Text = "Body text that wraps."; toast.Launch = “Id=123"; toast.Image.Src = "ms-appx:///images/graySquare.png";
ToastNotificationManager.CreateToastNotifier().Show(toast.CreateNotification()); |
Location
| Windows Phone 7 |
|
watcher = new GeoCoordinateWatcher(); watcher.PositionChanged += watcher_PositionChanged; watcher.TryStart(false, TimeSpan.FromMilliseconds(2000));
// Handler private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) { … } |
| Windows 8 |
|
locator = new Geolocator(); locator.PositionChanged += locator_PositionChanged;
// Handler private void locator_PositionChanged(Geolocator sender, PositionChangedEventArgs e) { … } |
Accelerometer
| Windows Phone 7 |
|
accelerometer = new Accelerometer(); accelerometer.ReadingChanged += ReadingChanged;
// Handler private void ReadingChanged(object sender, AccelerometerReadingEventArgs e) { … } |
| Windows 8 |
|
accelerometer = Accelerometer.GetDefault(); if (accelerometer != null) { accelerometer.ReadingChanged += ReadingChanged; }
// Handler private void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e) { … } |
Open Photo
| Windows Phone 7 |
|
chooser = new PhotoChooserTask(); chooser.Completed += chooser_Completed; void chooser_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(e.ChosenPhoto); } } |
| Windows 8 |
|
var picker = new FileOpenPicker(); picker.ViewMode = PickerViewMode.Thumbnail; picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; picker.FileTypeFilter.Add(".jpg"); var file = await picker.PickSingleFileAsync();
if (file != null) { … } |
Capture Photo
| Windows Phone 7 |
|
chooser = new CameraCaptureTask (); chooser.Completed += chooser_Completed; void chooser_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(e.ChosenPhoto); } } |
| Windows 8 |
|
var camera = new CameraCaptureUI(); var file = await camera.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (file != null) { … } |
Capture Video – System UI
On Windows Phone 7 there is no system-provided UI for capturing video (though a custom UI can be created). On Windows 8, the system UI can be used to capture MP4 and WMV files.
| Windows Phone 7 |
|
Not an option |
| Windows 8 |
|
CameraCaptureUI camera = new CameraCaptureUI(); camera.VideoSettings.Format = CameraCaptureUIVideoFormat.Mp4;
StorageFile file = await camera.CaptureFileAsync(CameraCaptureUIMode.Video);
if (file != null) { … } |
Capture Video – Custom UI
Custom video capture on both platforms involves placing an element on the screen that will display the video preview, creating a capture device, connecting the visual element with the capture device, and capturing the video to a target file.
| Windows Phone 7 |
|
videoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
captureSource = new CaptureSource(); fileSink = new FileSink();
fileSink.IsolatedStorageFileName = "CameraMovie.mp4"; fileSink.CaptureSource = captureSource;
videoBrush.SetSource(captureSource); viewfinderRectangle.Fill = videoBrush;
captureSource.Start(); |
| Windows 8 |
|
mediaCapture = new MediaCapture(); await mediaCapture.InitializeAsync();
previewElement.Source = mediaCapture;
storageFile = await KnownFolders.VideosLibrary.CreateFileAsync("CameraMovie.mp4");
profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);
await mediaCapture.StartRecordToStorageFileAsync(profile, storageFile); |
Very helpful.
Reblogged this on Invoke IT Limited.
Nice list. One thing I found out about the Win8 Navigation though is that e.ClickedItem has to be a simple type such as a string or the app may fail to suspend.
Came here to say the same thing about Navigation. It accepts objects but suspending throws exceptions for anything except a string. Very annoying actually.