Blog
Theme Manager for Windows Phone

Theme Manager for Windows Phone

One of Windows Phones features is the ability for a user to switch between light and dark themes. However as a developer creating a good experience in your apps that looks good in both themes can be a challenge. What's worse is it sometimes leads to apps that look great in one theme but not the other.

Unfortunately there is also no official easy way to tell the phone you want your app to run with a particular theme. Instead it's a manual process of either setting the colour of every object, or manually loading a theme in the apps start-up.

Thankfully there is a better way and it comes in the form of a NuGet package. By simply installing the wp-thememanager package you can call ThemeManager.ToLightTheme() in your apps contructor to make the theme light, or ThemeManager.ToDarkTheme() to make it dark.

1/// <summary>
2/// Constructor for the Application object.
3/// </summary>
4public App()
5{
6 // Global handler for uncaught exceptions.
7 UnhandledException += Application_UnhandledException;
8
9 // Standard Silverlight initialization
10 InitializeComponent();
11
12 // Phone-specific initialization
13 InitializePhoneApplication();
14
15 ThemeManager.ToLightTheme();
16
17 // Other code that might be here already...
18}

Links to resources

WP Theme Manager on GitHub
Jeff Wilcox blog post on the project
NuGet Package for WP Theme Manager

Two Google Maps Tips

Two Google Maps Tips

Centre a map on a collection of pins

The basic way to centre a Google Map is to give it co-ordinates of where you want the map to centre. But what if you have a collection of pin/markers and you want to show all of them but don't know beforehand where they will be.

The solution is to create a LatLngBounds object and for each of your pins call the extend method of your bounds object. Once this is done call fitBounds on your map.

1var bounds = new google.maps.LatLngBounds();
2
3$.each(mapMarkers(), function(index, value) {
4 bounds.extend(value.marker.position);
5});
6
7map.fitBounds(bounds);

Loading a map in a hidden div

The reason for doing this could be that you have a set of tabs and a non-visible one contains the Google Map. If you instantiate a Google Map when it isn't visible you end up with the smallest map size possible.

One popular solution for this is to only create the map when the tab is being displayed, which is a good option as it means the map is only loaded when it's viewed. However if your using something like Knockout to bind you've views to a model it may not be possible to attach an event to the tab change.

Google Maps actually have an event handler for just this scenario called resize. You simply need to trigger it at the point in which you can size the map.

1google.maps.event.trigger(map, 'resize')
Integrating with the Windows Phone 8 Media Hub

Integrating with the Windows Phone 8 Media Hub

One of my favourite features of Windows Phone is the ability for apps to integrate with the different hubs on the phone. The Music and Video hub lets developers do this not only by having their app listed in the apps section, but also by feeding data to the new and history lists plus the currently playing tile.

To add a track to the history list have a look at the following code:

1MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();
2mediaHistoryItem.ImageStream = image;
3mediaHistoryItem.Source = "";
4mediaHistoryItem.Title = "Track Title";
5mediaHistoryItem.PlayerContext["playSong"] = "Track Identifier";
6MediaHistory mediaHistory = MediaHistory.Instance;
7
8mediaHistory.WriteRecentPlay(mediaHistoryItem);

To add a track to the new list is relatively similar:

1MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();
2mediaHistoryItem.ImageStream = image;
3mediaHistoryItem.Source = "";
4mediaHistoryItem.Title = "Track Title";
5mediaHistoryItem.PlayerContext["playSong"] = "Track Identifier";
6MediaHistory mediaHistory = MediaHistory.Instance;
7
8mediaHistory.WriteAcquiredItem(mediaHistoryItem);

Some things to note though; Your image must be 173 x 173px, a title must be given that describes what is playing (not just the name of your app) and the keyString property should be populated with an identifier that you can use to identify the track.
When a user presses the tile in either of the new or history lists it will trigger your app to be opened. In the OnNavigatedTo even you can query the QueryString from the NavigationContext to find the identifier for the song selected by the user.

1bool _historyItemLaunch = false; // Indicates whether the app was launched from a MediaHistoryItem.
2const String _playSongKey = "playSong"; // Key for MediaHistoryItem key-value pair.
3Song _playingSong = null; // The song to play.
4
5protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
6{
7 MediaLibrary library = new MediaLibrary();
8
9 if (NavigationContext.QueryString.ContainsKey(_playSongKey))
10 {
11 // We were launched from a history item.
12 // Change _playingSong even if something was already playing
13 // because the user directly chose a song history item.
14
15 // Use the navigation context to find the song by name.
16 String songToPlay = NavigationContext.QueryString[_playSongKey];
17
18 foreach (Song song in library.Songs)
19 {
20 if (0 == String.Compare(songToPlay, song.Name))
21 {
22 _playingSong = song;
23 break;
24 }
25 }
26
27 // Set a flag to indicate that we were started from a
28 // history item and that we should immediately start
29 // playing the song after the UI has finished loading.
30 _historyItemLaunch = true;
31 }
32}
33
34private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
35{
36 if (_historyItemLaunch)
37 {
38 // We were launched from a history item, start playing the song.
39 if (_playingSong != null)
40 {
41 MediaPlayer.Play(_playingSong);
42 }
43 }
44}

There is also an option to write to the now playing section of the hub, however if you are playing your track using BackgroundAudioPlaer this is not needed as it is automatically handled for you from the track information.