Hi folks,

In this article I’d like to present all the new Windows Phone 7.5 Mango APIs. The goal is to inform developers who aren’t familiar with Mango of what new APIs are available. Since there are “1,500” new APIs we won’t be able to deep-dive into APIs with code samples. We’ll examine the new APIs and their related class diagrams. Most APIs should be fairly straightforward to professional .net developers who should be familiar with Microsoft’s API style. Each section of this article will also contain external links for those wishing to learn more about the APIs, featuresets and their usages.

How was this article composed? Who is it meant for?

This article is geared towards professional .net developers who want to learn about the WP7.5 Mango release. If you can look at a Microsoft API and figure out what it does, then this article is for you. If can’t look at an API and figure it out, then this article isn’t for you. We won’t have any samples of code usage inline in the article. Though there are external links for most topics.

Using the Framework Design Studio I compared all the WP7.0 (NoDo) assemblies with the WP7.5 (Mango) assemblies. We’ll review those changes in this article.

You can download the generated diff reports from @ http://JustinAngel.net/storage/MangoWp7ToWp71Reports.zip

Table of Contents

Sensors API: overview, SensorBase and other supporting classes

A new overall class hierarchy has been added to support Sensor readings from various sensors. In WP7.1 we only had Acceleromators. In WP7.5 the API has also been expanded to support the Compasses, Gyroscope and combined “Motion” APIs.

As you can see the new SensorBase<TSensorReading> class is the base class for all the new sensor classes. This architecture is a very elegant solution to making Sensor APIs consistent across multiple devices.

public abstract class SensorBase <TSensorReading> : IDisposable where TSensorReading : ISensorReading { public event EventHandler <SensorReadingEventArgs<TSensorReading>> CurrentValueChanged; public TSensorReading CurrentValue { get ; } public bool IsDataValid { get ; } public TimeSpan TimeBetweenUpdates { get ; set ; } public virtual void Start(); public virtual void Stop(); }

public interface ISensorReading { DateTimeOffset Timestamp { get ; } }

public class SensorReadingEventArgs <T> : EventArgs where T : ISensorReading { public T SensorReading { get ; set ; } }

Sensor API: Gyroscope and Compass

Two new Sensors now supported in WP7.5 are the Gyroscope and Compass APIs. They follow the pattern we just saw above of inheriting from SensorBase<ISensorReading> and implementing their own sensor reading event arguments.

public sealed class Compass : SensorBase<CompassReading> { public Compass(); public static bool IsSupported { get ; internal set ; } public event EventHandler <CalibrationEventArgs> Calibrate; }

public struct CompassReading : ISensorReading { public DateTimeOffset Timestamp { get ; internal set ; } public double HeadingAccuracy { get ; internal set ; } public double TrueHeading { get ; internal set ; } public Vector3 MagnetometerReading { get ; internal set ; } public double MagneticHeading { get ; internal set ; } }

public sealed class Gyroscope : SensorBase<GyroscopeReading> { public Gyroscope(); public static bool IsSupported { get ; internal set ; } }

public struct GyroscopeReading : ISensorReading { public DateTimeOffset Timestamp { get ; internal set ; } public Vector3 RotationRate { get ; internal set ; } }

Sensor APIs: Combined Motion API

An additional new type of Sensor readings is the new “Motion” API which takes input from all other available sensors and provides sensor-independent motion information. It’s recommended developers use this API whenever applicable to allow apps to work on as many devices as possible regardless of low-level supported sensors.

public sealed class Motion : SensorBase<MotionReading> { public Motion(); public static bool IsSupported { get ; internal set ; } public event EventHandler <CalibrationEventArgs> Calibrate; }

public struct MotionReading : ISensorReading



{

public DateTimeOffset Timestamp { get ; internal set ; }

public AttitudeReading Attitude { get ; internal set ; }

public Vector3 DeviceAcceleration { get ; internal set ; }

public Vector3 Gravity { get ; internal set ; }

public Vector3 DeviceRotationRate { get ; internal set ; }

}

public struct AttitudeReading : ISensorReading { public DateTimeOffset Timestamp { get ; internal set ; } public float Yaw { get ; internal set ; } public float Pitch { get ; internal set ; } public float Roll { get ; internal set ; } public Quaternion Quaternion { get ; internal set ; } public Matrix RotationMatrix { get ; internal set ; } }

Sensor APIs: changes to the Accelerometer API

The original API for WP7 Accelerometer was written back when there was only one Sensor API to support. As you’ve seen there is a new Sensor architectureand some elements of the Accelerometer API are now obsolete in favour of the new Sensor API conventions.

public sealed class Accelerometer : SensorBase<AccelerometerReading>

{

public static bool IsSupported { get ; internal set ; }

public SensorState State { get ; }

[ Obsolete ( "use CurrentValueChanged" )]

public event EventHandler <AccelerometerReadingEventArgs> ReadingChanged;

}

public struct AccelerometerReading : ISensorReading { public DateTimeOffset Timestamp { get ; internal set ; } public Vector3 Acceleration { get ; internal set ; } }

For more reading on the Sensor APIs and how to use them see MSDN’s section on Sensors for Windows Phone.

Camera API

Managed camera access for non-OEM apps has been added as part of the Mango release. You can read more about how to use this API on MSDN @ Camera and Photos for Windows Phone.

It’s easy to see that the core of this new API is the newly exposed Camera class and its inheriting class PhotoCamera that’s used for still shots.

public abstract class Camera : IDisposable { public static bool IsCameraTypeSupported(CameraType type); public CameraType CameraType { get ; protected set ; } public IEnumerable <Size> AvailableResolutions { get ; } public Size Resolution { get ; set ; } public Size PreviewResolution { get ; } public double Orientation { get ; } public event EventHandler <CameraOperationCompletedEventArgs> Initialized; public void Dispose(); }

public sealed class PhotoCamera : Camera { public PhotoCamera(CameraType type); public PhotoCamera(); public void Focus(); public void FocusAtPoint( double x, double y); public void CancelFocus(); public void GetPreviewBufferArgb32( int [] pixelData); public void GetPreviewBufferY( byte [] pixelData); public void GetPreviewBufferYCbCr( byte [] pixelData); public bool IsFlashModeSupported(FlashMode mode); public void CaptureImage(); public bool IsFocusSupported { get ; } public bool IsFocusAtPointSupported { get ; } public YCbCrPixelLayout YCbCrPixelLayout { get ; } public FlashMode FlashMode { get ; set ; } public event EventHandler <CameraOperationCompletedEventArgs> AutoFocusCompleted; public event EventHandler CaptureStarted; public event EventHandler <ContentReadyEventArgs> CaptureThumbnailAvailable; public event EventHandler <ContentReadyEventArgs> CaptureImageAvailable; public event EventHandler <CameraOperationCompletedEventArgs> CaptureCompleted; }

There are a few new event handlers and Enums used in PhotoCamera and Camera classes.

public enum CameraType

{

Primary,

FrontFacing,

}

public enum FlashMode { On = 1, Off = 2, Auto = 3, RedEyeReduction = 4, } public class CameraOperationCompletedEventArgs : EventArgs { public CameraOperationCompletedEventArgs( bool succeeded, Exception exception); public Exception Exception { get ; } public bool Succeeded { get ; } } public sealed class ContentReadyEventArgs : EventArgs { public Stream ImageStream { get ; } }

Video cameras as enabled as an extension method on VideoBrush through CameraVideoBrushExtensions.

public static class CameraVideoBrushExtensions { public static void SetSource( this VideoBrush brush, Camera camera); }

CameraButtons expose static events related to the shutter button.

public static class CameraButtons { public static event EventHandler ShutterKeyPressed; public static event EventHandler ShutterKeyHalfPressed; public static event EventHandler ShutterKeyReleased; }

A preview of the current image in the camera is available via the PhotoCamera.GetPreviewBufferYCbCr() method. The information describing the contents of that preview is available through the YCbCrPixelFormat class.

public sealed class YCbCrPixelLayout { public int RequiredBufferSize { get ; internal set ; } public int YPitch { get ; internal set ; } public int YXPitch { get ; internal set ; } public int YOffset { get ; internal set ; } public int CbPitch { get ; internal set ; } public int CbXPitch { get ; internal set ; } public int CbOffset { get ; internal set ; } public int CrPitch { get ; internal set ; } public int CrXPitch { get ; internal set ; } public int CrOffset { get ; internal set ; } }

The last API for the Camera Mango featureset is the addition of the MediaLibrary.SavePictureToCameraRoll() method. With it developers can create custom camera apps that save to the same location as the WP7 built-in camera app.

public sealed class MediaLibrary : IDisposable { public MediaLibrary(); public MediaLibrary( MediaSource mediaSource); public void Dispose(); public Picture SavePictureToCameraRoll( string name, byte [] imageBuffer); public Picture SavePictureToCameraRoll( string name, Stream source); public Picture SavePicture( string name, byte [] imageBuffer); public Picture SavePicture( string name, Stream source); public Picture GetPictureFromToken( string token); public AlbumCollection Albums { get ; } public ArtistCollection Artists { get ; } public GenreCollection Genres { get ; } public bool IsDisposed { get ; } public MediaSource MediaSource { get ; } public PictureCollection Pictures { get ; } public PlaylistCollection Playlists { get ; } public PictureAlbum RootPictureAlbum { get ; } public PictureCollection SavedPictures { get ; } public SongCollection Songs { get ; } }

Background API: overview and BackgroundTask class

There are new background processing related featuresets in mango: Audio, scheduled tasks, background transfers and toasts. As you can see from the diagram above there’s a common base class BackgroundAgent used by the 2 music streaming background agents and the 1 scheduled task background agent. Note that background transfers doesn’t have it’s own publicly exposed background agent.

public abstract class BackgroundAgent { protected internal BackgroundAgent(); protected void NotifyComplete(); protected void Abort(); protected internal virtual void OnCancel(); }

As with the rest of the featuresets we’ll be discussing in this article, we won’t review how to create a background agent. Read more on background agents on MSDN’s Background Agents for Windows Phone.

Background API: Background Audio and streaming background Audio

As part of the new Mango featureset to support audio playback while apps are in the background there are 2 new background agents we can inherit from and implement. First is the AudioPlayerAgent that can be used for any media type Windows Phone can directly play from a Uri. The second background agent is AudioStreamingAgent for otherwise unsupported streaming media formats that need some pre-processing (such as shoutcast, icecast and RTSP) using a custom Silverlight MediaStreamSource.

public class AudioPlayerAgent : BackgroundAgent { protected virtual void OnUserAction( BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param); protected virtual void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState); protected virtual void OnError(BackgroundAudioPlayer player, AudioTrack track, Exception error, bool isFatal); }

public class AudioStreamingAgent : BackgroundAgent { protected virtual void OnBeginStreaming(AudioTrack track, AudioStreamer streamer); protected internal override void OnCancel(); }

As we can see both of these are based on having an AudioTrack instance that contains information on the currently playing audio.

public class AudioTrack : IEditableObject { public AudioTrack(); public AudioTrack(Uri source, string title, string artist, string album, Uri albumArt); public AudioTrack( Uri source, string title, string artist, string album, Uri albumArt, string tag, EnabledPlayerControls enabledControls); public void BeginEdit(); public void CancelEdit(); public void EndEdit(); public Uri Source { get ; set ; } public string Title { get ; set ; } public string Artist { get ; set ; } public string Album { get ; set ; } public string Tag { get ; set ; } public Uri AlbumArt { get ; set ; } public EnabledPlayerControls PlayerControls { get ; set ; } public TimeSpan Duration { get ; } }

[ Flags ] public enum EnabledPlayerControls : long { None = 0, SkipNext = 1, SkipPrevious = 2, FastForward = 4, Rewind = 8, Pause = 16, All = Pause | Rewind | FastForward | SkipPrevious | SkipNext, }

The AudioPlayerAgent receives notifications whenever a user action happens (in the top media bar) and the playback status has changed.

public enum PlayState { Unknown, Stopped, Paused, Playing, BufferingStarted, BufferingStopped, TrackReady, TrackEnded, Rewinding, FastForwarding, Shutdown, Error, }

public enum UserAction { Stop = 1, Pause = 2, Play = 3, SkipNext = 4, SkipPrevious = 5, FastForward = 6, Rewind = 7, Seek = 8, }

Whenever the playstate changes or a user action has occurred, the background agent can respond interacting directly with audio playback through the BackgroundAudioPlayer.

public sealed class BackgroundAudioPlayer { public void Play(); public void Pause(); public void Stop(); public void FastForward(); public void Rewind(); public void SkipNext(); public void SkipPrevious(); public void Close(); public static BackgroundAudioPlayer Instance { get ; } public PlayState PlayerState { get ; } public AudioTrack Track { get ; set ; } public TimeSpan Position { get ; set ; } public double BufferingProgress { get ; } public bool CanPause { get ; } public bool CanSeek { get ; } public double Volume { get ; set ; } public Exception Error { get ; } public event EventHandler PlayStateChanged; }

We previously mentioned there are two background audio agents. The first used for straight up Uri playback, and the other for custom MediaStreamSource playback. For the latter you’ll have to use an AudioStreamer in order to provide the MediaStreamSource.

public sealed class AudioStreamer { public void SetSource(MediaStreamSource source); }

For more information on how to implement mango background audio playback see MSDN’s Background Audio Overview for Windows Phone.

Background API: Data Transfer APIs

As part of the mango featureset that allows apps to download and upload files while the app is in the background, developers can add new BackgroundTrasnferRequests to the BackgroundTransferService. The BackgroundTransferService will then schedule the download/upload transfers based on the overall transfer queue and network requirements.

public static class BackgroundTransferService { public static BackgroundTransferRequest Find( string requestId); public static void Add(BackgroundTransferRequest request); public static void Remove(BackgroundTransferRequest request); public static IEnumerable <BackgroundTransferRequest> Requests { get ; } }

public sealed class BackgroundTransferRequest : IDisposable { public BackgroundTransferRequest(Uri requestUri); public BackgroundTransferRequest(Uri requestUri, Uri downloadLocation); public void Dispose(); public string RequestId { get ; } public Uri RequestUri { get ; } public string Tag { get ; set ; } public Uri DownloadLocation { get ; set ; } public Uri UploadLocation { get ; set ; } public IDictionary < string , string > Headers { get ; } public string Method { get ; set ; } public TransferPreferences TransferPreferences { get ; set ; } public TransferStatus TransferStatus { get ; } public Exception TransferError { get ; } public long TotalBytesToReceive { get ; } public long TotalBytesToSend { get ; } public long BytesReceived { get ; } public long BytesSent { get ; } public long StatusCode { get ; } public event EventHandler <BackgroundTransferEventArgs> TransferStatusChanged; public event EventHandler <BackgroundTransferEventArgs> TransferProgressChanged; }

public enum TransferPreferences { None, AllowCellular, AllowBattery, AllowCellularAndBattery, }

By signing up to events on the BackgroundTransferRequest events it’s possible to receive notifications whenever the download/upload status changes and their respective status.

public sealed class BackgroundTransferEventArgs : EventArgs { public BackgroundTransferEventArgs(BackgroundTransferRequest request); public BackgroundTransferRequest Request { get ; } }

public enum TransferStatus { None, Transferring, Waiting, WaitingForWiFi, WaitingForExternalPower, WaitingForExternalPowerDueToBatterySaverMode, WaitingForNonVoiceBlockingNetwork, Paused, Completed, Unknown, }

public sealed class BackgroundTransferInternalException : SystemException { }

Scheduling & Background API: Alarms, Reminders, Periodic Tasks and Resource Intensive Tasks

Using the new scheduling API it’s possible to add scheduled reminder, alarms and tasks. Using the ScheduledActionService we can add, retrieve and test any of the aforementioned tasks.

public sealed class ScheduledActionService { public static void Add(ScheduledAction action); public static ScheduledAction Find( string name); public static IEnumerable <T> GetActions<T>() where T : ScheduledAction; public static void Remove( string name); public static void Replace(ScheduledAction action); public static void LaunchForTest( string name, TimeSpan delay); } public sealed class SchedulerServiceException : SystemException { }

To add Alarms or Reminders simply instantiate those classes and add them to the ScheduleActionService. For more on this topic see MSDN’s Alarms and Reminders Overview for Windows Phone.

public abstract class ScheduledNotification : ScheduledAction { public virtual string Content { get ; set ; } public RecurrenceInterval RecurrenceType { get ; set ; } public virtual string Title { get ; set ; } }

public enum RecurrenceInterval { None, Daily, Weekly, Monthly, EndOfMonth, Yearly, }

public sealed class Alarm : ScheduledNotification { public Alarm( string name); public Uri Sound { get ; set ; } public override string Title { get ; set ; } }

public sealed class Reminder : ScheduledNotification { public Reminder( string name); public Uri NavigationUri { get ; set ; } }

It’s also possible to create scheduled tasks where we can execute arbitrary code in a ScheduleTaskAgent.

public abstract class ScheduledTaskAgent : BackgroundAgent { protected internal abstract void OnInvoke(ScheduledTask task); [EditorBrowsable(EditorBrowsableState.Never)] protected internal override sealed void OnCancel(); }

To schedule running a ScheduleTaskAgent use either a PeriodicTask or for more resource intensive tasks (execution time, WiFi-only, device lock, etc) use the ResourceIntensiveTask. Both inherit from ScheduledTask. For more on this topic and the distinction between resource intensive and non-resource intensive tasks see MSDN’s Background Agents Overview for Windows Phone.

public abstract class ScheduledTask : ScheduledAction

{

public override DateTime BeginTime { get ; set ; }







public override DateTime ExpirationTime { get ; set ; }

public string Description { get ; set ; }





public DateTime LastScheduledTime { get ; internal set ; }



public AgentExitReason LastExitReason { get ; internal set ; }

}

public enum AgentExitReason { None, Completed, Aborted, MemoryQuotaExceeded, ExecutionTimeExceeded, UnhandledException, Terminated, Other, }

public sealed class PeriodicTask : ScheduledTask { public PeriodicTask( string name); }

public sealed class ResourceIntensiveTask : ScheduledTask { public ResourceIntensiveTask( string name); }

Background API: Programmatic Toast Notifications

Using the new ShellToast class it is possible for background agents to show a toast notification that’ll act as a deep link back to the application. It’s important to mention that this API will not work for in-app notifications, and will only show toast notifications when invoked from a background agent. For more on that see Den Delimarsky’s ShellToast on Windows Phone.

public class ShellToast { public void Show(); public string Title { get ; set ; } public string Content { get ; set ; } public Uri NavigationUri { get ; set ; } }

Appointments and Contacts API: Overview

Using the new PhoneDataSharingContext classes it’s possible to search for Appointments and Contacts on the phone, register for a search completed events and check the EventsArgs for the results. We can see the parallels between Appointments and Contacts from the class diagram above. Even though they are both independent they both share the same search-driven architecture. The resulting Contact and Appointment classes are very informative so we’ll address each in its own section in this article.

public class PhoneDataSharingContext { protected PhoneDataSharingContext( string baseUri); protected IEnumerable <T> ExecuteRequest<T>( string query); protected string BaseUri { get ; } }

Both Appointments and Contacts’ search allow to filter based on user accounts with the relevant classes shown here:

public sealed class Account { public string Name { get ; internal set ; } public StorageKind Kind { get ; internal set ; } }

public enum StorageKind { Phone, WindowsLive, Outlook, Facebook, Other, }

For more on how to access Appointments and Contacts see MSDN’s Contacts and Calendar for Windows Phone.

Appointments

As we’ve previously mentioned access to Appointments starts of with searching for appointments, registering for the async results events and iterating over the EventArgs results.

public sealed class Appointments : PhoneDataSharingContext { public const int DefaultMaximumItems = 100; public void SearchAsync( DateTime startTimeInclusive, DateTime endTimeInclusive, object state); public void SearchAsync( DateTime startTimeInclusive, DateTime endTimeInclusive, int maximumItems, object state); public void SearchAsync( DateTime startTimeInclusive, DateTime endTimeInclusive, Account account, object state); public void SearchAsync( DateTime startTimeInclusive, DateTime endTimeInclusive, int maximumItems, Account account, object state); public IEnumerable <Account> Accounts { get ; } public event EventHandler <AppointmentsSearchEventArgs> SearchCompleted; }

public sealed class AppointmentsSearchEventArgs : EventArgs { public DateTime StartTimeInclusive { get ; internal set ; } public DateTime EndTimeInclusive { get ; internal set ; } public IEnumerable <Appointment> Results { get ; internal set ; } public object State { get ; internal set ; } }

The appointments themselves can be accessed after the search is complete.

public sealed class Appointment { public string Subject { get ; internal set ; } public string Location { get ; internal set ; } public DateTime StartTime { get ; internal set ; } public DateTime EndTime { get ; internal set ; } public bool IsAllDayEvent { get ; internal set ; } public AppointmentStatus Status { get ; internal set ; } public string Details { get ; internal set ; } public Attendee Organizer { get ; internal set ; } public IEnumerable <Attendee> Attendees { get ; } public bool IsPrivate { get ; internal set ; } public Account Account { get ; internal set ; } }

public enum AppointmentStatus { Free, Tentative, Busy, OutOfOffice, }

public sealed class Attendee { public string DisplayName { get ; internal set ; } public string EmailAddress { get ; internal set ; } }

Contacts use the same async search pattern used for appointments.

public sealed class Contacts : PhoneDataSharingContext { public void SearchAsync( string filter, FilterKind filterKind, object state); public IEnumerable <Account> Accounts { get ; } public event EventHandler <ContactsSearchEventArgs> SearchCompleted; }

public sealed class ContactsSearchEventArgs : EventArgs { public FilterKind FilterKind { get ; internal set ; } public string Filter { get ; internal set ; } public IEnumerable <Contact> Results { get ; internal set ; } public object State { get ; internal set ; } }

When searching for contacts it’s possible to filter the search based on name, phone number, email address and whether the contact tile is pinned to the phone home screen.

public enum FilterKind

{

None,

PinnedToStart,

EmailAddress,

PhoneNumber,

DisplayName,

}

The results of a search for contacts is the Contact class which references many additional supporting classes.

public sealed class Contact { public Stream GetPicture(); public string DisplayName { get ; internal set ; } public CompleteName CompleteName { get ; internal set ; } public IEnumerable <ContactPhoneNumber> PhoneNumbers { get ; } public IEnumerable <ContactEmailAddress> EmailAddresses { get ; } public IEnumerable <ContactAddress> Addresses { get ; } public IEnumerable <ContactCompanyInformation> Companies { get ; } public IEnumerable < string > Websites { get ; } public IEnumerable < string > SignificantOthers { get ; } public IEnumerable < string > Children { get ; } public IEnumerable < string > Notes { get ; } public IEnumerable < DateTime > Birthdays { get ; } public bool IsPinnedToStart { get ; internal set ; } public IEnumerable <Account> Accounts { get ; } }

public sealed class CompleteName { public string FirstName { get ; internal set ; } public string YomiFirstName { get ; internal set ; } public string LastName { get ; internal set ; } public string YomiLastName { get ; internal set ; } public string MiddleName { get ; internal set ; } public string Title { get ; internal set ; } public string Nickname { get ; internal set ; } public string Suffix { get ; internal set ; } }

public sealed class ContactPhoneNumber { public string PhoneNumber { get ; internal set ; } public PhoneNumberKind Kind { get ; internal set ; } public IEnumerable <Account> Accounts { get ; } } public enum PhoneNumberKind { Mobile, Home, Work, Company, Pager, HomeFax, WorkFax, }



public sealed class ContactEmailAddress { public string EmailAddress { get ; internal set ; } public EmailAddressKind Kind { get ; internal set ; } public IEnumerable <Account> Accounts { get ; } } public enum EmailAddressKind { Personal, Work, Other, }

public sealed class ContactAddress { public CivicAddress PhysicalAddress { get ; internal set ; } public AddressKind Kind { get ; internal set ; } public IEnumerable <Account> Accounts { get ; } }

public sealed class ContactCompanyInformation { public string CompanyName { get ; internal set ; } public string YomiCompanyName { get ; internal set ; } public string OfficeLocation { get ; internal set ; } public string JobTitle { get ; internal set ; } public IEnumerable <Account> Accounts { get ; } }

New Launchers and Choosers

There are 8 new Launchers & Choosers in Mango and we’ll review all of them in this section.

The ShareStatusTask and ShareLinkTask share content on social media accounts the user has previously linked to (facebook, twitter, windows live, etc). For more on how to use the sharing tasks see MSDN’s How to: Use the Share Status Task for Windows Phone and How to: Use the Share Link Task for Windows Phone.

public abstract class ShareTaskBase { public void Show(); }

public sealed class ShareStatusTask : ShareTaskBase { public string Status { get ; set ; } } public sealed class ShareLinkTask : ShareTaskBase { public Uri LinkUri { get ; set ; } public string Title { get ; set ; } public string Message { get ; set ; } }

The ConnectionSettingsTask allows apps to launch into 4 settings screen on the phone: Airplane Mode, WiFi Settings, Bluetooth Settings and Cellular & Data settings. For a sample on how to use this task see MSDN’s How to: Use the Connection Settings Task for Windows Phone.

public sealed class ConnectionSettingsTask { public void Show(); public ConnectionSettingsType ConnectionSettingsType { get ; set ; } }

public enum ConnectionSettingsType { WiFi, Bluetooth, Cellular, AirplaneMode, }

The BingMapsTask launches the map application with a specific latitude and longitude combination or just a search term. For instructions on how to use this task see MSDN’s How to: Use the Bing Maps Task for Windows Phone.

public sealed class BingMapsTask { public void Show(); public GeoCoordinate Center { get ; set ; } public string SearchTerm { get ; set ; } public double ZoomLevel { get ; set ; } }

The BingMapsDirectionsTask launches the maps app with driving directions between two latitude and longitude coordinates. For instructions on how to use this task see MSDN’s How to: Use the Bing Maps Directions Task for Windows Phone.

public sealed class BingMapsDirectionsTask { public void Show(); public LabeledMapLocation Start { get ; set ; } public LabeledMapLocation End { get ; set ; } }

public sealed class LabeledMapLocation { public LabeledMapLocation(); public LabeledMapLocation( string label, GeoCoordinate location); public string Label { get ; set ; } public GeoCoordinate Location { get ; set ; } }

The GameInviteTask is an API that can only be used by previously approved Xbox Live titles (currently there are less than 100 of those) to start multiplayer gaming sessions. For more on this task see MSDN’s How to: Use the Game Invite Task for Windows Phone.

public sealed class GameInviteTask : ChooserBase<TaskEventArgs> { public override void Show(); public string SessionId { get ; set ; } }

The SaveRingtoneTask launches a save dialog for a new phone ringtone based on a Uri. Note that even though the Uri can point to any file Uri there are very specific requirements for the audio file that you’ll want to make sure your ringtone meets. For more information on this task and the aforementioned requirements see MSDN’s How to: Use the Save Ringtone Task for Windows Phone.

public sealed class SaveRingtoneTask : ChooserBase<TaskEventArgs> { public override void Show(); public Uri Source { get ; set ; } public string DisplayName { get ; set ; } public bool IsShareable { get ; set ; } }

The AddressChooserTask allows the user to select an address from their contacts list. For more information on how to use this task see MSDN’s How to: Use the Address Chooser Task for Windows Phone.

public sealed class AddressChooserTask : ChooserBase<AddressResult> { public override void Show(); } public sealed class AddressResult : TaskEventArgs { public AddressResult(); public AddressResult(TaskResult taskResult); public string Address { get ; internal set ; } public string DisplayName { get ; internal set ; } }

The SaveContactTask shows the user a pre-populated new contact dialogue and will return if the user actually created a new contact or not. For more on how to use this task see MSDN’s How to: Use the Save Contact Task for Windows Phone.

public sealed class SaveContactTask : ChooserBase<SaveContactResult> { public override void Show(); public string FirstName { get ; set ; } public string LastName { get ; set ; } public string MiddleName { get ; set ; } public string Nickname { get ; set ; } public string Suffix { get ; set ; } public string Company { get ; set ; } public string Title { get ; set ; } public string MobilePhone { get ; set ; } public string HomePhone { get ; set ; } public string WorkPhone { get ; set ; } public string PersonalEmail { get ; set ; } public string WorkEmail { get ; set ; } public string OtherEmail { get ; set ; } public string HomeAddressStreet { get ; set ; } public string HomeAddressCity { get ; set ; } public string HomeAddressState { get ; set ; } public string HomeAddressZipCode { get ; set ; } public string HomeAddressCountry { get ; set ; } public string WorkAddressStreet { get ; set ; } public string WorkAddressCity { get ; set ; } public string WorkAddressState { get ; set ; } public string WorkAddressZipCode { get ; set ; } public string WorkAddressCountry { get ; set ; } public string Website { get ; set ; } public string Notes { get ; set ; } public string JobTitle { get ; set ; } }

public class SaveContactResult : TaskEventArgs { public SaveContactResult(); public SaveContactResult(TaskResult taskResult); }

Back to the table of contents

Changes and additions to existing Launchers and Choosers

With Mango a few of the existing Launchers and Choosers have received new features. We’ll review these changes in this section.

The MediaPlayerLauncher task can now specify the Orientation of the video player. When trying to playback videos recorded on mobile devices the new portrait setting would be extremely useful.

public class MediaPlayerLauncher { public void Show(); public Uri Media { get ; set ; } public MediaPlaybackControls Controls { get ; set ; } public MediaLocationType Location { get ; set ; } public MediaPlayerOrientation Orientation { get ; set ; } }

public enum MediaPlayerOrientation { Landscape, Portrait, }

The EmailComposeTask now allows develoepers to specify suggested BCC emails and the CodePage to be used in globalization scenarios.

public sealed class EmailComposeTask { public void Show(); public string Body { get ; set ; } public string Bcc { get ; set ; } public string Cc { get ; set ; } public int ? CodePage { get ; set ; } public string Subject { get ; set ; } public string To { get ; set ; } }

The EmailResult class which is returned from the EmailAddressChooserTask now also contains a DisplayName and in addition to the email address chosen by the user.

public class EmailResult : TaskEventArgs { public EmailResult(); public EmailResult(TaskResult taskResult); public string Email { get ; internal set ; } public string DisplayName { get ; internal set ; } }

The WebBrowserTask now uses a strongly-typed Uri type property instead of a loosely typed String Url property. For any apps upgraded to Mango that use WebBrowserTask there should be a build warning asking you to switch to the new task.

public sealed class WebBrowserTask { public void Show(); [ Obsolete ( "Please use Uri property" )] public string URL { get ; set ; } public Uri Uri { get ; set ; } }

Back to the table of contents

Secondary Tiles and primary tile improvements

Using the new StandardTileData and adding those the ShellTile.Create() static method it is possible to add secondary tiles that deep link into application.

public abstract class ShellTileData { public string Title { get ; set ; } }

public class StandardTileData : ShellTileData { public int ? Count { get ; set ; } public Uri BackgroundImage { get ; set ; } public string BackContent { get ; set ; } public string BackTitle { get ; set ; } public Uri BackBackgroundImage { get ; set ; } }

public sealed class ShellTile { public static void Create(Uri navigationUri, ShellTileData initialData); public void Update(ShellTileData data); public void Delete(); public static string ConvertToXMLFormat( string str); public Uri NavigationUri { get ; } public static IEnumerable <ShellTile> ActiveTiles { get ; } }

An interesting hidden feature of this API is that it allows to also modify the primary tile pinned to the phone home page. So if the application itself is pinned to the homepage it’ll be in the ShellTile.ActiveTiles. That’s extremely useful if you want to add a background image and text to the primary tile. More on that is available on Pavel Yosifovich’s blog post Dynamic Live Tiles in Windows Phone 7.

Another change introduced in Mango is adding an overload for ShellTileSchedule so it can work with secondary tiles. Using this new API it is possible to set an interval in which the secondary tile images are updated from a remote server.

public class ShellTileSchedule { public ShellTileSchedule(); public ShellTileSchedule(ShellTile tileId); public void Start(); public void Stop(); public UpdateRecurrence Recurrence { get ; set ; } public int MaxUpdateCount { get ; set ; } public DateTime StartTime { get ; set ; } public UpdateInterval Interval { get ; set ; } public Uri RemoteImageUri { get ; set ; } }

For more on secondary tiles see MSDN’s Tiles for Windows Phone.

Mixed XNA and Silverlight apps

With Mango we can now have apps that run both Silverlight content and XNA content. There are two core usecases for this API we need to think about: (1) Adding Silverlight Content (e.g. a menu system) to an XNA game (2) Adding XNA content (e.g. a 3d image) to a Silverlight app. Thinking about these 2 usecases makes it easier to understand the new API introduced for this featureset.

The first step in creating a mixed XNA and Silverlight app is to make sure that SharingMode=True whenever we have mixed content rendering on the screen.

public static class GraphicsDeviceExtensions { public static void SetSharingMode( this GraphicsDevice device, bool enabled); }

Use the UIElementRenderer to setup Silverlight elements to render in mixed mode.

public class UIElementRenderer : IDisposable { public UIElementRenderer(UIElement rootElement, int textureWidth, int textureHeight); public void Render(); protected virtual void Dispose( bool disposing); public void Dispose(); public UIElement Element { get ; } public Texture2D Texture { get ; } }

We would also have to invoke the UIElementRenderer.Render() within our game loop. Use the new GamerTimer timer for your game loop in mixed mode apps.

public sealed class GameTimer : IDisposable { public static void SuppressFrame(); public static void ResetElapsedTime(); public void Start(); public void Stop(); public void Dispose(); public int DrawOrder { get ; set ; } public int FrameActionOrder { get ; set ; } public TimeSpan UpdateInterval { get ; set ; } public int UpdateOrder { get ; set ; } public event EventHandler <GameTimerEventArgs> Draw; public event EventHandler < EventArgs > FrameAction; public event EventHandler <GameTimerEventArgs> Update; }

public sealed class GameTimerEventArgs : EventArgs { public GameTimerEventArgs(); public GameTimerEventArgs( TimeSpan totalTime, TimeSpan elapsedTime); public TimeSpan ElapsedTime { get ; } public TimeSpan TotalTime { get ; } }

For XNA apps that use GraphicsDeviceManager they’ll need to switch over and use the new SharedGraphicsDeviceManager class.

public class SharedGraphicsDeviceManager : IGraphicsDeviceService, IDisposable , IApplicationService, IApplicationLifetimeAware { public static readonly int DefaultBackBufferHeight; public static readonly int DefaultBackBufferWidth; public void ApplyChanges(); void IDisposable .Dispose(); void IApplicationService.StartService(ApplicationServiceContext context); void IApplicationService.StopService(); void IApplicationLifetimeAware.Starting(); void IApplicationLifetimeAware.Started(); void IApplicationLifetimeAware.Exiting(); void IApplicationLifetimeAware.Exited(); public static SharedGraphicsDeviceManager Current { get ; } public GraphicsDevice GraphicsDevice { get ; } public GraphicsProfile GraphicsProfile { get ; set ; } public int MultiSampleCount { get ; set ; } public SurfaceFormat PreferredBackBufferFormat { get ; set ; } public int PreferredBackBufferHeight { get ; set ; } public int PreferredBackBufferWidth { get ; set ; } public DepthFormat PreferredDepthStencilFormat { get ; set ; } public PresentInterval PresentationInterval { get ; set ; } public RenderTargetUsage RenderTargetUsage { get ; set ; } public bool SynchronizeWithVerticalRetrace { get ; set ; } public event EventHandler < EventArgs > DeviceCreated; public event EventHandler < EventArgs > DeviceDisposing; public event EventHandler < EventArgs > DeviceReset; public event EventHandler < EventArgs > DeviceResetting; public event EventHandler < EventArgs > Disposed; }

For more information on how to setup mixed XNA and Silverlight apps see AppHub’s guide for XNA devs using mixed mode apps, Peter Kuhn’s guide for Silverlight devs using mixed mode apps and AppHub’s sample Paddle Battle game.

LINQ-to-SQL and Local Database

As part of Mango Linq-to-SQL running on SQL CE is now supported. Linq2SQL is huge and contains a lot of classes that are new to WP7. We can’t possibly cover all the API for those classes in this article so we’ll just see a huge class diagram and move on. For more information on the core Linq-to-SQL API see MSDN’s Local Database for Windows Phone.

There are however a few Linq-to-SQL APIs that are WP7 specific and we’ll cover those in a bit more depth. All these Linq2SQL WP7 specific APIs are part of the new Microsoft.Phone.Data.Linq and Microsoft.Phone.Data.Linq.Mapping namespaces.

The DatabaseSchemaUpdater is used to make sure that different versions of the application could upgrade the previously installed databases from older versions. When a database is first created it gets the DatabaseSchemaVersion of 0 or any other value you’d like to give it. It is then possible to use that version number to programmatically add database objects (tables, columns, etc) and update the schema version.

public sealed class DatabaseSchemaUpdater { public void AddTable<T>(); public void AddColumn<T>( string columnPropertyName); public void AddIndex<T>( string indexName); public void AddAssociation<T>( string associationPropertyName); public void Execute(); public DataContext Context { get ; } public int DatabaseSchemaVersion { get ; set ; } }

public static class Extensions { public static DatabaseSchemaUpdater CreateDatabaseSchemaUpdater( this DataContext dataContext); }

The next part of WP7 specific Linq-to-SQL API is adding support for database Indexes which doesn’t exist in the desktop version of Linq-to-SQL. This is an important feature since there is no other way to execute DDL (i.e. “create index” statements) on the WP7 SQL CE database. If you expect a high volume of data in a SQL CE Table it’s best to optimize for query scenarios and index the “where” SQL SELECT query columns.

[ AttributeUsage ( AttributeTargets .Class, AllowMultiple = true , Inherited = false )] public sealed class IndexAttribute : Attribute { public string Name { get ; set ; } public bool IsUnique { get ; set ; } public string Columns { get ; set ; } }

public abstract class MetaIndex { public abstract string IndexName { get ; } public abstract ReadOnlyCollection <MetaIndexedColumn> Columns { get ; } public abstract bool IsUnique { get ; } public abstract MetaType DeclaringType { get ; } }

public abstract class MetaIndexedColumn { public abstract MetaDataMember Column { get ; } public abstract SortOrder SortOrder { get ; } } public enum SortOrder { Ascending, Descending, }

Back to the table of contents

Search Extensibility

If your app has dynamic server data it’s a great idea to expose a few bing consumable XML files on the server that would deep link into your app from the WP7 search. There’s very little new API for the Mango feature that lets WP7 search deep link into apps. The client side changes involve adding the appropriate <Extension> tags to the WmAppManifest and <ExtensionInfo> tags to the Extras file.

Most of the work for this feature would have to happen on the server-side to expose XML files with the appropriate search data and deep links.

For more on this feature see MSDN’s Search Extensibility for Windows Phone.

Back to the table of contents

Sockets: IP and DNS Addresses

Sockets are a pretty large API and most devs will only work with frameworks based on this API. For these reasons we’ll skip the C# definitions for classes in this namespace and instead focus on overall featuresets and class diagrams.

As Sockets are all about direct communication between WP7 and a remote machine DNS and IP addresses classes have been introduced to Mango.

Back to the table of contents

Sockets: DNS Resolution

The DNS resolution API is WP7-specific and is used to convert from a DnsEndPoint (host name and port) to a more specific IPEndPoint that is used by Sockets.

Sockets: Socket class and SocketAsyncEventArgs

The Socket class is used to connect to an IPEndPoint and then send & receive SocketAsyncEventArgs from that Socket.

Back to the table of contents

Sockets: UDP

As part of Silverlight 4 UDP support for single-source and multi-source communication has been added to WP7.

Shell UI: New ProgressIndicator, and changes to ApplicationBar & SystemTray

There are parts of the application UI that are actually part of the OS shell. The top “SystemTray” and the bottom “ApplicationBar” are two such UI elements.

The ApplicationBar class has added support to show the ApplicationBar as collapsed (similar to how it’s shown in the Music & Video hub) and specify the height used for both the default and minimal mode.

public sealed class ApplicationBar : IApplicationBar

{ public ApplicationBar();

public bool IsVisible { get ; set ; }

public double Opacity { get ; set ; }

public bool IsMenuEnabled { get ; set ; }

public Color BackgroundColor { get ; set ; }

public Color ForegroundColor { get ; set ; }

public ApplicationBarMode Mode { get ; set ; }

public double DefaultSize { get ; }

public double MiniSize { get ; } public IList Buttons { get ; }

public IList MenuItems { get ; }

public event EventHandler <ApplicationBarStateChangedEventArgs> StateChanged;

}

public interface IApplicationBar { bool IsVisible { get ; set ; } double Opacity { get ; set ; } bool IsMenuEnabled { get ; set ; } Color BackgroundColor { get ; set ; } Color ForegroundColor { get ; set ; } ApplicationBarMode Mode { get ; set ; } double DefaultSize { get ; } double MiniSize { get ; } IList Buttons { get ; } IList MenuItems { get ; } event EventHandler <ApplicationBarStateChangedEventArgs> StateChanged; }

public enum ApplicationBarMode { Default, Minimized, }

The SystemTray previously only had an IsVisible property to hide the top bar. The main reason why app developers hid the top bar in apps was due to a theme colour clash. So with Mango you can use your brand colours on the SystemTray by setting the new attached dependency properties. As a reminder a pattern of a static GetFoo, SetFoo and FooProperty members is an attached dependency property pattern.

public class SystemTray : DependencyObject { public static readonly DependencyProperty IsVisibleProperty; public static readonly DependencyProperty OpacityProperty; public static readonly DependencyProperty ForegroundColorProperty; public static readonly DependencyProperty BackgroundColorProperty; public static readonly DependencyProperty ProgressIndicatorProperty; public SystemTray(); public static void SetIsVisible(DependencyObject element, bool isVisible); public static bool GetIsVisible(DependencyObject element); public static void SetOpacity(DependencyObject element, double opacity); public static double GetOpacity(DependencyObject element); public static void SetForegroundColor(DependencyObject element, Color color); public static Color GetForegroundColor(DependencyObject element); public static void SetBackgroundColor(DependencyObject element, Color color); public static Color GetBackgroundColor(DependencyObject element); public static void SetProgressIndicator(DependencyObject element, ProgressIndicator progressIndicator); public static ProgressIndicator GetProgressIndicator(DependencyObject element); public static bool IsVisible { get ; set ; } public static double Opacity { get ; set ; } public static Color ForegroundColor { get ; set ; } public static Color BackgroundColor { get ; set ; } public static ProgressIndicator ProgressIndicator { get ; set ; } }

A SystemTray.ProgressBar can be set to show a unified WP7 UI for any in-app process progress taking place (e.g. web requests). An example of how to do so can be found on MSDN’s ProgressIndicator Class.

public class ProgressIndicator : DependencyObject { public static readonly DependencyProperty IsVisibleProperty; public static readonly DependencyProperty IsIndeterminateProperty; public static readonly DependencyProperty TextProperty; public static readonly DependencyProperty ValueProperty; public ProgressIndicator(); public bool IsVisible { get ; set ; } public bool IsIndeterminate { get ; set ; } public string Text { get ; set ; } public double Value { get ; set ; } } Back to the table of contents

Bing Maps changes: Random XAML elements positioning

With Mango the Bing Maps SDK has had only 1 change in it. Attached Dependency properties have been added to the MapPlayer class that allow to position random XAML elements in a latitude and longitude coordinate or relative to the rest of the map.

public sealed class MapLayer : MapLayerBase, IProjectable { public static readonly DependencyProperty PositionProperty; public static readonly DependencyProperty PositionRectangleProperty; public static readonly DependencyProperty PositionOriginProperty; public static readonly DependencyProperty PositionOffsetProperty; public MapLayer(); public override void AddChild(UIElement element, GeoCoordinate location); public override void AddChild(UIElement element, GeoCoordinate location, Point offset); public override void AddChild(UIElement element, GeoCoordinate location, PositionOrigin origin); public override void AddChild(UIElement element, LocationRect locationRect); public static GeoCoordinate GetPosition(DependencyObject dependencyObject); public static void SetPosition(DependencyObject dependencyObject, GeoCoordinate position); public static LocationRect GetPositionRectangle( DependencyObject dependencyObject); public static void SetPositionRectangle(DependencyObject dependencyObject, LocationRect rect); public static PositionOrigin GetPositionOrigin( DependencyObject dependencyObject); public static void SetPositionOrigin(DependencyObject dependencyObject, PositionOrigin origin); public static Point GetPositionOffset(DependencyObject dependencyObject); public static void SetPositionOffset(DependencyObject dependencyObject, Point point); public void ProjectionUpdated(ProjectionUpdateLevel updateLevel); public MapBase ParentMap { get ; } }

Back to the table of contents

Removing Pages from the backstack frame journal

A common requirement in NoDo was to block the automatic frame navigation from navigating back into certain pages (e.g. splash page, registration page, etc). There are a few tricks in NoDo that allowed for a decent UX in the absence of any API for directly controlling the backstack. With Mango it is now possible to remove the last page from the back stack.

public sealed class NavigationService { public bool Navigate(Uri source); public void GoForward(); public void GoBack(); public void StopLoading(); public JournalEntry RemoveBackEntry(); public Uri Source { get ; set ; } public Uri CurrentSource { get ; internal set ; } public bool CanGoForward { get ; } public bool CanGoBack { get ; } public IEnumerable <JournalEntry> BackStack { get ; } public event NavigationFailedEventHandler NavigationFailed; public event NavigatingCancelEventHandler Navigating; public event NavigatedEventHandler Navigated; public event NavigationStoppedEventHandler NavigationStopped; public event FragmentNavigationEventHandler FragmentNavigation; public event EventHandler <JournalEntryRemovedEventArgs> JournalEntryRemoved; }

public sealed class JournalEntry : DependencyObject { public Uri Source { get ; set ; } }

public sealed class JournalEntryRemovedEventArgs : EventArgs { public JournalEntry Entry { get ; } }

public class PhoneApplicationFrame : Frame { public static readonly DependencyProperty OrientationProperty; public PhoneApplicationFrame(); public JournalEntry RemoveBackEntry(); public PageOrientation Orientation { get ; internal set ; } public IEnumerable <JournalEntry> BackStack { get ; } public event EventHandler <OrientationChangedEventArgs> OrientationChanged; public event EventHandler <ObscuredEventArgs> Obscured; public event EventHandler Unobscured; public event EventHandler <CancelEventArgs> BackKeyPress; public event EventHandler <JournalEntryRemovedEventArgs> JournalEntryRemoved; }

Pages can respond to being removed from the back stack by overriding the new OnRemovedFromJournal method.

public class PhoneApplicationPage : Page { public static readonly DependencyProperty SupportedOrientationsProperty; public static readonly DependencyProperty OrientationProperty; public static readonly DependencyProperty ApplicationBarProperty; public PhoneApplicationPage(); protected virtual void OnOrientationChanged(OrientationChangedEventArgs e); protected virtual void OnBackKeyPress(CancelEventArgs e); protected virtual void OnRemovedFromJournal(JournalEntryRemovedEventArgs e); public SupportedPageOrientation SupportedOrientations { get ; set ; } public PageOrientation Orientation { get ; set ; } public IApplicationBar ApplicationBar { get ; set ; } public IDictionary < string , object > State { get ; } public event EventHandler <OrientationChangedEventArgs> BeginLayoutChanged; public event EventHandler <OrientationChangedEventArgs> OrientationChanged; public event EventHandler <CancelEventArgs> BackKeyPress; }

Back to the table of contents

Device Information and Network Information

The new DeviceStatus class has strongly-typed properties that can be used to replace the older DeviceExtendedProperties and it also has previously unavailable device information properties.

public static class DeviceStatus { public static bool IsKeyboardDeployed { get ; } public static bool IsKeyboardPresent { get ; } public static PowerSource PowerSource { get ; } public static long ApplicationCurrentMemoryUsage { get ; } public static long ApplicationPeakMemoryUsage { get ; } public static long ApplicationMemoryUsageLimit { get ; } public static long DeviceTotalMemory { get ; } public static string DeviceName { get ; } public static string DeviceFirmwareVersion { get ; } public static string DeviceHardwareVersion { get ; } public static string DeviceManufacturer { get ; } public static event EventHandler KeyboardDeployedChanged; public static event EventHandler PowerSourceChanged; }

public enum PowerSource { Battery, External, }

The new DeviceNetworkInformation class exposes information about the network status of the mobile device.

public static class DeviceNetworkInformation { public static void ResolveHostNameAsync( DnsEndPoint endPoint, NetworkInterfaceInfo networkInterface, NameResolutionCallback callback, object context); public static void ResolveHostNameAsync(DnsEndPoint endPoint, NameResolutionCallback callback, object context); public static bool IsCellularDataRoamingEnabled { get ; } public static bool IsWiFiEnabled { get ; } public static bool IsCellularDataEnabled { get ; } public static string CellularMobileOperator { get ; } public static bool IsNetworkAvailable { get ; } public static event EventHandler <NetworkNotificationEventArgs> NetworkAvailabilityChanged; }

public sealed class NetworkNotificationEventArgs : EventArgs { public NetworkNotificationType NotificationType { get ; } public NetworkInterfaceInfo NetworkInterface { get ; } }

The new MediaCapabilities exposes information on whether or not smooth adaptive video streaming is supported on the current device or not.

public static class MediaCapabilities { public static bool IsMultiResolutionVideoSupported { get ; } }

Back to the table of contents

WebBrowser control changes: HTML5 GeoLocation and NavigationFailed event

The WebBrowser control in Mango supports HTML5 GeoLocation after setting IsGeolocationEnabled=True. It also has a new NavigationFailed event.

public sealed class WebBrowser : Control { public static readonly DependencyProperty SourceProperty; public static readonly DependencyProperty BaseProperty; public static readonly DependencyProperty IsScriptEnabledProperty; public static readonly DependencyProperty IsGeolocationEnabledProperty; public WebBrowser(); public override void OnApplyTemplate(); public void Navigate(Uri uri); public void Navigate(Uri uri, byte [] postData, string additionalHeaders); public void NavigateToString( string html); public object InvokeScript( string scriptName, params string [] args); public object InvokeScript( string scriptName); public string SaveToString(); public Uri Source { get ; set ; } public string Base { get ; set ; } public bool IsScriptEnabled { get ; set ; } public bool IsGeolocationEnabled { get ; set ; } public event EventHandler <NavigatingEventArgs> Navigating; public event EventHandler <NavigationEventArgs> Navigated; public event LoadCompletedEventHandler LoadCompleted; public event NavigationFailedEventHandler NavigationFailed; public event EventHandler <NotifyEventArgs> ScriptNotify; }

Back to the table of contents

Network Request Preference and Requirements

The new WebRequestExtensions and SocketExtensions classes define extension methods that can be used to associate a specific network interface (e.g. 3G vs. WiFi) with specific network requests.

public static class WebRequestExtensions { public static void SetNetworkPreference( this WebRequest request, NetworkSelectionCharacteristics preference); public static void SetNetworkRequirement( this WebRequest request, NetworkSelectionCharacteristics requirement); public static NetworkInterfaceInfo GetCurrentNetworkInterface( this WebRequest request); }

public static class SocketExtensions { public static void SetNetworkPreference( this Socket socket, NetworkSelectionCharacteristics preference); public static void SetNetworkRequirement( this Socket socket, NetworkSelectionCharacteristics requirement); public static NetworkInterfaceInfo GetCurrentNetworkInterface( this Socket socket); public static void AssociateToNetworkInterface( this Socket socket, NetworkInterfaceInfo networkInterface); }

Back to the table of contents

Xbox Live: Render Xbox Live Avatars in XNA

With the introduction of Microsoft.Xna.Framework.Avatar assembly it is now possible for Xbox Live Titles to render Xbox Live Avatars using the new AvatarRenderer class. Note, only Xbox Live Titles can use this functionality. Because of that limited subset of apps that have access to this functionality and because of the sheer size of the new assembly we’ll only briefly glance at a class diagram and move on.

Back to the table of contents

Xbox Live: Avatar Assets

Xbox Live-titles (and only xbox live titles) can now take advantage of the new SignedInGamerExtensions and award assets to Xbox Live Avatars. Again, this feature is only available for Xbox-Live titles.

public static class SignedInGamerExtensions { public static IAsyncResult BeginAwardAvatarAssets( this SignedInGamer gamer, string [] assetKeys, AsyncCallback callback, object state); public static void EndAwardAvatarAssets( this SignedInGamer gamer, IAsyncResult result); public static void AwardAvatarAssets( this SignedInGamer gamer, string [] assetKeys); }

Back to the table of contents

Custom Linq Providers

A core piece of LINQ that has been missing from NoDo was the ability to create custom Linq Providers. With Mango the IQueryProvider and IQueryable interfaces have been added. With the new support for custom LINQ providers it is now possible to use one of the many open source LINQ providers. for more on implementing a custom LINQ provider and the importance of IQueryProvider see Matt Warren’s LINQ: Building an IQueryable Provider.

public interface IQueryProvider { IQueryable CreateQuery(Expression expression); IQueryable<TElement> CreateQuery<TElement>(Expression expression); object Execute(Expression expression); TResult Execute<TResult>(Expression expression); }

public interface IQueryable : IEnumerable { Expression Expression { get ; } Type ElementType { get ; } IQueryProvider Provider { get ; } }

The additional classes of EnurableQuery, EnurableQuery<T>, EnurableExecutor, EnumrableExecutor<T> and Queryable are all helper classes used when implementing a custom LINQ provider. We won’t expend on them further in this blog post.

Back to the table of contents

Dynamically compiled Lambda Expressions and Reflection.Emit

A small chunk of Refleciton.Emit has been added to Mango in order to enable the Expression.Compile() method. Using Expression.Compile() it is possible to build at runtime an expression tree, compile it and then execute it. All at runtime. We’ll only examine the change to LambdaExpression in greater detail. For more information on this topic see MSDN’s Expression(TDelegate).Compile Method.

public class LambdaExpression : Expression { public Delegate Compile(); public Expression Body { get ; } public ReadOnlyCollection <ParameterExpression> Parameters { get ; } }

Back to the table of contents

mscorib.Extensions: SIMD/ARM-NEON XNA support

Mango allows to accelerate calculation operations on SIMD/ARM-NEON capable devices. Which means that XNA calculations on Vector, Matrix and other types would be somewhat faster. To take advantage of this new feature apply the attribute wit he SIMD flag on the relevant assemblies. For more on this see Enable SIMD support in Mango.

[ AttributeUsage ( AttributeTargets .Assembly)] public sealed class CodeGenerationAttribute : Attribute { public CodeGenerationAttribute(CodeGenerationFlags flags); public int CodeGenerationFlags { get ; } } [ Flags ] public enum CodeGenerationFlags { EnableFPIntrinsicsUsingSIMD = 1, }

Back to the table of contents

mscorlib.Extensions: Mutex

A trimmed down version of Mutex wait handle class has been added to Mango.

public sealed class Mutex : WaitHandle { public Mutex( bool initiallyOwned, string name); public void ReleaseMutex(); public override bool WaitOne(); public override bool WaitOne( int millisecondsTimeout); }

Back to the table of contents

mscorlib.Extensions: INotifyPropertyChanging

The INotifyProperyChanging interface has been added as part of Mango. This API is the counterpart for the existing INotifyPropertyChanged interface. Currently the only feature using this new interface is Linq-to-SQL, but we could definitely take advantage of it for other 3rd party usages. For more on that see Claus Konrad’s WP7/7.1: Where is INotifiyPropertyChanging defined?.

public interface INotifyPropertyChanging { event PropertyChangingEventHandler PropertyChanging; }

public delegate void PropertyChangingEventHandler( object sender, PropertyChangingEventArgs e);

public class PropertyChangingEventArgs : EventArgs { public PropertyChangingEventArgs( string propertyName); public virtual string PropertyName { get ; } }

Back to the table of contents

mscorlib.Extensions: RSA Cryptography

With Mango the RsaCryptoServiceProvider has been added to enable asymmetric encryption and decryption. For more information on how to use RsaCryptoServiceProvider with a custom server backend see Dustin Horne’s Asymmetric Encryption and Signing with RSA in Silverlight.

Silverlight 4: Base-Class Library changes in mscorlib assembly

WP7 NoDo was based on Silverlight 3. With the release Mango all the changes done in Silverlight 4 were migrated back to WP7. Most of the changes are in the System.Windows assembly (Silverlight) and the majority of other changes are in the mscorlib BCL (base class library) assembly. All the changes made in Silverlight 4 to the BCL were additions of new members to existing classes. The one exception to that is the removal of the TaiwanCalender class from Mango. The class diagram and code snippets below contain only the new members added to the BCL in Mango.

public sealed class AppDomain { public Assembly [] GetAssemblies(); } public static class BitConverter { public static Int64 DoubleToInt64Bits( Double value); public static Double Int64BitsToDouble( Int64 value); } public static class GC { public static Int32 MaxGeneration { get ; } } public sealed class Guid { public static Guid Parse( String input); public static Guid ParseExact( String input, String format); public static Boolean TryParse( String input, out Guid result); public static Boolean TryParseExact( String input, String format, out Guid result); } public sealed class String { public static String Concat( IEnumerable < String > values); public static String Concat<T>( IEnumerable <T> values); public static Boolean IsNullOrWhiteSpace( String value); public static String Join( String separator, IEnumerable < String > values); public static String Join<T>( String separator, IEnumerable <T> values); public static String Join( String separator, params Object [] values); } public sealed class TimeSpan { public String ToString( String format); public String ToString( String format, IFormatProvider formatProvider); public static TimeSpan Parse( String input, IFormatProvider formatProvider); public static TimeSpan ParseExact( String input, String [] formats, IFormatProvider formatProvider); public static TimeSpan ParseExact( String input, String format, IFormatProvider formatProvider); public static TimeSpan ParseExact( String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles); public static TimeSpan ParseExact( String input, String [] formats, IFormatProvider formatProvider, TimeSpanStyles styles); public static Boolean TryParse( String input, IFormatProvider formatProvider, out TimeSpan result); public static Boolean TryParseExact( String input, String format, IFormatProvider formatProvider, out TimeSpan result); public static Boolean TryParseExact( String input, String [] formats, IFormatProvider formatProvider, out TimeSpan result); public static Boolean TryParseExact( String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result); public static Boolean TryParseExact( String input, String [] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result); } public abstract class Type { public Boolean IsNested { get ; } } public sealed class Version { public static Version Parse( String input); public static Boolean TryParse( String input, out Version result); } public interface ISymbolDocumentWriter { void SetCheckSum( Guid algorithmId, Byte [] checkSum); void SetSource( Byte [] source); } [ FlagsAttribute ] public enum TimeSpanStyles { None, AssumeNegative } public class FileStream : Stream , IDisposable { public virtual void Flush( Boolean flushToDisk); } public abstract class Stream : IDisposable { public void CopyTo( Stream destination); public void CopyTo( Stream destination, Int32 bufferSize); } public sealed class IsolatedStorageFile : IDisposable { public void CopyFile( String sourceFileName, String destinationFileName); public void CopyFile( String sourceFileName, String destinationFileName, Boolean overwrite); public DateTimeOffset GetCreationTime( String path); public DateTimeOffset GetLastAccessTime( String path); public DateTimeOffset GetLastWriteTime( String path); public void MoveDirectory( String sourceDirectoryName, String destinationDirectoryName); public void MoveFile( String sourceFileName, String destinationFileName); } public class IsolatedStorageFileStream : FileStream { public override void Flush( Boolean flushToDisk); } public sealed class StringBuilder { public StringBuilder Clear(); } public static class Interlocked { public static Object CompareExchange( ref Object location1, Object value, Object comparand); } public static class Monitor { public static void Enter( Object obj, ref Boolean lockTaken); public static void TryEnter( Object obj, ref Boolean lockTaken); public static void TryEnter( Object obj, TimeSpan timeout, ref Boolean lockTaken); public static void TryEnter( Object obj, Int32 millisecondsTimeout, ref Boolean lockTaken); }

Silverlight 4: System.Windows Silverlight changes

Silverlight 4 is it’s own product release and quite an extensive one at that. We’ll briefly cover the new API added to the System.Windows assembly as part of the Mango upgrade to Silverlight 4. For those of you interested in more details on Silverlight 4 changes from Silverlight 3 see Tim Heuer’s Silverlight 4 Beta – A guide to the new features. Please note, the API we’ll see in this section is the API that was added in Mango and not all the API in these classes.

In the System.Collections.ObjectModel namespace we’ve got new constructors for the ObservableCollection class that allow to easy convert a standard List<T> to an ObservableCollection<T>.

public class ObservableCollection <T> { public ObservableCollection <T>(List list); public ObservableCollection <T>( IEnumerable collection); }

In the System.ComponentModel namespace we’ve got a few new APIs for databinding and some additions to design-time.

public sealed class AlternateContentPropertyAttribute : Attribute { public AlternateContentPropertyAttribute(); } public sealed class DataErrorsChangedEventArgs : EventArgs { public DataErrorsChangedEventArgs( String propertyName); public String PropertyName { get ; } } public static class DesignerProperties { public static Boolean RefreshOnlyXmlnsDefinitionsOnAssemblyReplace { get ; } } public interface ICollectionViewFactory { ICollectionView CreateView(); } public interface IDataErrorInfo { String Error { get ; } String this [ String columnName] { get ; } } public interface IEditableCollectionView { Boolean CanAddNew { get ; } Boolean CanCancelEdit { get ; } Boolean CanRemove { get ; } Boolean IsAddingNew { get ; } Boolean IsEditingItem { get ; } NewItemPlaceholderPosition NewItemPlaceholderPosition { get ; set ; } Object CurrentAddItem { get ; } Object CurrentEditItem { get ; } Object AddNew(); void CancelEdit(); void CancelNew(); void CommitEdit(); void CommitNew(); void EditItem( Object item); void Remove( Object item); void RemoveAt( Int32 index); } public interface INotifyDataErrorInfo { Boolean HasErrors { get ; } IEnumerable GetErrors( String propertyName); event EventHandler ErrorsChanged; } public interface ISupportInitialize { void BeginInit(); void EndInit(); } public enum NewItemPlaceholderPosition { None, AtEnd }

There are quite a bit of peer automation related changes in the System.Windows.Automation.* namespaces, but since Automation Peers are not supported on WP7 there’s no point in going over those in any great detail.

In the System.Windows namespace we have a few changes: Support for the new Tap & Hold & DoubleTap events, programmatic control of the Clipboard, Right-To-Left support and a few others. There are also a few “junk” changes to support features that aren’t supported in Mango and we won’t review those here.

public static class Clipboard { public static Boolean ContainsText(); public static String GetText(); public static void SetText( String text); } public class DependencyObjectCollection <T> { public virtual sealed Int32 IndexOf(T item); public virtual sealed void Insert( Int32 index, T item); public event NotifyCollectionChangedEventHandler CollectionChanged; } public enum FlowDirection { LeftToRight, RightToLeft } public abstract class FrameworkElement : UIElement { public FlowDirection FlowDirection { get ; set ; } public static readonly DependencyProperty FlowDirectionProperty; } public abstract class UIElement : DependencyObject { public event EventHandler DoubleTap; public event EventHandler Hold; public event EventHandler Tap; public event TextCompositionEventHandler TextInput; public event TextCompositionEventHandler TextInputStart; public event TextCompositionEventHandler TextInputUpdate; public static readonly DependencyProperty AllowDropProperty; public static readonly RoutedEvent DoubleTapEvent; public static readonly RoutedEvent HoldEvent; public static readonly RoutedEvent TapEvent; public static readonly RoutedEvent TextInputEvent; public static readonly RoutedEvent TextInputStartEvent; public static readonly RoutedEvent TextInputUpdateEvent; } public sealed class VisualStateGroup : DependencyObject { public VisualState CurrentState { get ; } }

The System.Windows.Controls and System.Windows.Controls.Primitives namespace has a few changes in it: The new ViewBox control, addition of ellipsis (“…”) text trimming to TextBlock, MVVM Button Commanding support, Video playback MediaElement timed markers and a few other features. The really interesting changes here is the introduction of a WP7 API for ScrollViewer.ManipulationMode for fine-tuned scrolling support on the phone. The ScrollViewer additions are exclusive to WP7 Mango.

public class ListBox { public void SelectAll(); } public sealed class MediaElement : FrameworkElement { public TimelineMarkerCollection Markers { get ; } public event TimelineMarkerRoutedEventHandler MarkerReached; } public sealed class PasswordBox : Control { public Double BaselineOffset { get ; } } public sealed class ScrollViewer : ContentControl { public ManipulationMode ManipulationMode { get ; set ; } public static ManipulationMode GetManipulationMode( DependencyObject element); public static void SetManipulationMode( DependencyObject element, ManipulationMode manipulationMode); public static readonly DependencyProperty ManipulationModeProperty; } public enum ManipulationMode { Control, System } public sealed class TextBlock { public Double BaselineOffset { get ; } public TextTrimming TextTrimming { get ; set ; } public static readonly DependencyProperty TextTrimmingProperty; } public class TextBox : Control { public Double BaselineOffset { get ; } } public sealed class Viewbox : FrameworkElement { public Viewbox(); public Stretch Stretch { get ; set ; } public StretchDirection StretchDirection { get ; set ; } public UIElement Child { get ; set ; } public static readonly DependencyProperty StretchDirectionProperty; public static readonly DependencyProperty StretchProperty; } public enum StretchDirection { UpOnly, DownOnly, Both }

In System.Windows.Documents a new RichTextBox control and many supporting classes have been added. We won’t review this control and it’s associated classes in-depth. For more information on this control see MSDN’s RichTextBox Overview.

In System.Windows.Data namespace there’s really one thing we care about: The addition of 5 new properties to the {Binding} syntax. There’s also a few other “junk” changes that aren’t applicable for WP7. which we won’t review here.

public class Binding : BindingBase { public Boolean ValidatesOnDataErrors { get ; set ; } public Boolean ValidatesOnNotifyDataErrors { get ; set ; } } public abstract class BindingBase { public Object FallbackValue { get ; set ; } public Object TargetNullValue { get ; set ; } public String StringFormat { get ; set ; } }

A big part of the changes done in System.Windows.Media namespace is around the introduction of VideoSink and AudioSink. In WP7 these provide access to the Microphone and Camera which are available through more phone specific APIs so it’s best to avoid these if possible.

There are few interesting changes in the System.Windows.Media namespace: support for Playready DRM DomainAcquirer, support for RichTextBox support for all fonts, The VideoBrush and a VisualTreeHelper.GetOpenPopups() method.

public class DomainAcquirer { public DomainAcquirer(); public String ChallengeCustomData { get ; set ; } [ SecuritySafeCriticalAttribute ] public void CancelAsync(); public void JoinDomainAsync( Guid serviceId, Guid accountId, Uri domainServerUrl, String friendlyName); public void LeaveDomainAsync( Guid serviceId, Guid accountId, Uri domainServerUrl); public event EventHandler JoinDomainCompleted; public event EventHandler LeaveDomainCompleted; protected virtual void OnCancel(); protected virtual void OnJoinDomain( Stream joinChallenge, Uri domainServerUri); protected virtual void OnLeaveDomain( Stream leaveChallenge, Uri domainServerUri); protected void SetJoinDomainResponse( Stream domainResponse); protected void SetLeaveDomainResponse( Stream domainResponse); } public class DomainOperationCompletedEventArgs : AsyncCompletedEventArgs { public Guid AccountId { get ; } public Guid ServiceId { get ; } public String ResponseCustomData { get ; } } public static class Fonts { public static ICollection SystemTypefaces { get ; } } public class Typeface { public Boolean TryGetGlyphTypeface( out GlyphTypeface glyphTypeface); } public sealed class GlyphTypeface { public Double Version { get ; } public String FontFileName { get ; } } public sealed class VideoBrush : TileBrush { public VideoBrush(); public String SourceName { get ; set ; } public void SetSource( CaptureSource source); public void SetSource( MediaElement source); public static readonly DependencyProperty SourceNameProperty; } public static class VisualTreeHelper { public static IEnumerable GetOpenPopups(); }

The System.Windows.Input namespace has a few interesting additions as-well: 2 new input scopes have been added, fine-grained control of IME (use of Latin keyboards for Asian languages input) and a few other changes.

public sealed class GestureEventArgs : RoutedEventArgs { public GestureEventArgs(); public Boolean Handled { get ; set ; } public Point GetPosition( UIElement relativeTo); } public enum ImeConversionModeValues { Alphanumeric, Native, Katakana, FullShape, Roman, CharCode, NoConversion, Eudc, Symbol, Fixed, DoNotCare } public sealed class InputMethod : DependencyObject { public static ImeConversionModeValues GetPreferredImeConversionMode( DependencyObject target); public static InputMethodState GetPreferredImeState( DependencyObject target); public static void SetPreferredImeConversionMode( DependencyObject target, ImeConversionModeValues value); public static void SetPreferredImeState( DependencyObject target, InputMethodState value); } public enum InputMethodState { Off, On, DoNotCare } public enum InputScopeNameValue { NumericPassword, Formula }

Back to the table of contents

Feedback? Leave a comment!

Feedback? Thoughts? Suggestions? Sound off in the comments!

Sincerely,

-- Justin Angel, Principal Engineer @ Nokia WP7