How to Share Maps Using the Share Charm in Windows Store Apps
Depending on the type of application you are creating, you may find it useful to be able to share a map with someone. Whether it’s a map of a single location or a map with a route on it, this can easily be accomplished in a Windows Store app. In this blog post we are going to take a look at two different ways you can share a map in a Windows Store app.
Sharing things is easy in Windows Store apps when using the Share charm. We can easily specify text or HTML that we want to share inside a message. There are two ways we can do share a map. The first is to use the Bing Maps REST Imagery service and generate an image of a map. The second method is to make use of the Bing Maps consumer site (https://bing.com/maps) and build a URL.
Creating a Map Image
The Bing Maps REST Imagery service makes it easy to generate an image of map. There are several different options and parameters that can be used to generate static map images. Here is one of the most basic structures for generating a static map image.
https://dev.virtualearth.net/REST/v1/Imagery/Map/ [ImagerySet] / [CenterPoint] / [ZoomLevel] ? [ImageOptionParameters]& key= [BingMapsKey] |
The ImagerySet parameter can have one of the following values:
Aerial |
AerialWithLabels |
Road |
OrdnanceSurvey (UK only) |
CollinsBart (London UK only) |
The CenterPoint value of the URL is used to center the map over a specific coordinate. This consists of the latitude and longitude values being separated by a comma. The ZoomLevel is an integer value between 1 and 19 that indicates the level at which the map image should zoom. The following are some of the image option parameters that can be used with the Imagery API.
Parameter |
Description |
declutterPins |
Specifies whether to change the display of overlapping pushpins so that they display separately on a map. (Optional) 1: Declutter pushpin icons. 0: Do not declutter pushpin icons. (default) |
format |
The image format to use for the static map. By default the best file format for a particular map style is used. (Optional) gif: GIF image format. jpeg: JPEG image format. JPEG format is the default for Road, Aerial and AerialWithLabels imagery. png: PNG image format. PNG is the default format for CollinsBart and OrdnanceSurvey imagery. |
mapArea |
The geographic area to display on the map. Required when a center point or set of route points are not specified. This is a comma separated set of numbers using the following format: “South Latitude,West Longitude,North Latitude,East Longitude” |
mapLayer |
A display layer that renders on top of the imagery set. The only value for this parameter is TrafficFlow. (Optional) Example: mapLayer=TrafficFlow |
mapSize |
A string that contains a width and a height separated by a comma. The width must be between 80 and 900 pixels and the height must be between 80 and 834 pixels. The default map size for static maps is 350 pixels by 350 pixels. (Optional) |
pushpin |
A series of values that include a Point value (latitude and longitude) with options to add a label of up to three (3) characters and to specify an icon style. You can specify up to 18 pushpins within a URL and 100 if you use the HTTP POST method and specify the pushpins in the body of the request. (Optional) A short form version of this parameter is available: pp |
There are many other parameters available that can be used to add routes as well. You can find full documentation on Bing Maps REST Imagery service on MSDN.
One nice thing about REST services is that they are very easy to test. Once you have created a REST request URL you can simply put it in the address bar of a browser to see the response.
Using this information we can create the following URL that opens an image of Bing Maps with the map centered on a specific location (Seattle - 47.60356,-122.32943) with a zoom level of 12, and the map view set to the road map view:
Here is the generated image:
Creating a URL to Bing Maps
The Bing Maps consumer site exposes a number of URL query parameters which can be used to load a custom map view. These parameters are very similar to the Bing Maps REST Imagery service. You can customize the URL to display specific search results, driving directions, or items in your “My Places” folder.
To create a URL to the Bing Maps consumer site, start with the base URL and then use parameters to specify the location and options such as zoom level, map view, search panels, and more. The base address you should use is https://bing.com/maps/default.aspx. The following is a list of some of the basic parameters you can use:
Parameter |
Description |
cp |
Defines where the center of the map should be. Use the following format for the cp parameter: Latitude~Longitude |
lvl |
Defines the zoom level of the map. Valid values are 1-19. This parameter is ignored if you don't include the cp parameter. |
style |
Defines the map view. Valid values for this parameter include: a: Display an aerial view of the map. r: Display a road view of the map. h: Display an aerial view of the map with labels. o: Use this value to display a bird's eye (oblique) view of the map. b: Display a bird's eye (oblique) with labels view of the map. u: Automatic |
trfc |
Specifies whether traffic information is included on the map. Omitting the trfc parameter produces the same results as trfc=0. |
You can find full documentation on creating URLs for the Bing Maps consumer site on the Bing Help website.
Using this information we can create the following URL that opens Bing Maps with the map centered on a specific location (Seattle - 47.60356,-122.32943) with a zoom level of 12, and the map view set to the road map view: https://bing.com/maps/default.aspx?cp=47.60356~-122.32943&lvl=12&style=r
Opening this URL in a browser will load up the Bing Maps consumer site centered over Seattle.
Sharing from a Windows Store App
Now that we understand the basics of generating a static map image and a link to the Bing Maps consumer site, we can use this to create a Windows Store app that allows us to share this information through the Share charm. For this app we will create a simple application that uses the Bing Maps Windows Store control. When the Share charm is activated it will use the center point and zoom level of the map to generate the map image and URL to the Bing Maps consumer site. In addition to this, we will also add a button to the app that will launch the share charm. You may find this useful in the future if you have a list of results and you want to let the user select a single result and share it all with a single touch.
To get started let’s open up Visual Studios and create a new project in your preferred language: JavaScript, C# or Visual Basic. Select the Blank App template and call the application BingMapsShareCharm and press OK.
Add a reference to the Bing Maps SDK. To do this, right click on the References folder and press Add Reference. Select Windows -> Extensions select Bing Maps for C#, C++ and Visual Basic or Bing Maps for JavaScript. If you do not see this option ensure that you have installed the Bing Maps SDK for Windows Store apps. While you are here, if using C# or Visual Basic, add a reference to the Microsoft Visual C++ Runtime Package as this is required by the Bing Maps SDK.
If you are using C# or Visual Basic you may notice that there is a little yellow indicator on the references that you just added. The reason for this is that in the C++ runtime package you have to set the Active solution platform in Visual Studio to one of the following options; ARM, x86 or x64. To do this, right click on the Solution folder and select Properties. Then go to Configuration Properties -> Configuration. Find your project and under the Platform column set the target platform. For this blog post I’m going to select x86. Press Ok and the yellow indicator should disappear from our references.
If you are using JavaScript right click on the js folder and select Add -> New Item. Create a new JavaScript file called ShareMap.js. We will put all our JavaScript for this application in there to keep things clean. Now open up the default.html file and update the HTML to the following:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>BingMapsShareCharm</title>
<!-- WinJS references -->
<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.1.0/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
<!-- BingMapsShareCharm references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>
<!-- Bing Map Control references -->
<script type="text/javascript" src="ms-appx:///Bing.Maps.JavaScript//js/veapicore.js"></script>
<!-- Our Bing Maps JavaScript Code -->
<script src="/js/ShareMap.js"></script>
</head>
<body>
<div id="MyMap"></div>
<button id="ShareBtn" style="position:absolute;top:0;left:400px;background-color:#000;">Share Location</button>
</body>
</html>
If you are using C# or Visual Basic open the MainPage.xaml file and add update the xaml to the following:
<Page
x:Class="BingMapsShareCharm.MainPage"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BingMapsShareCharm"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:Bing.Maps"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<m:Map Name="MyMap" Credentials="YOUR_BING_MAPS_KEY"/>
<StackPanel Margin="10" Height="40" VerticalAlignment="Top" HorizontalAlignment="Center" Background="Black">
<Button Content="Share Location" Tapped="ShareLocation_Tapped"/>
</StackPanel>
</Grid>
</Page>
Be sure to add your Bing Maps key into the XAML.
Next we can add the functionality to power the application. Regardless of the language you are using you will have to do the following tasks:
1. Get a reference to the Share charm for the current view using the DataTransferManager.
2. Add an event handler when the user navigates to the app that is fired when data is requests by the Share charm. Remove this event handler when the user leaves the app.
3. Since we are using Bing Maps generate a session key from the map after the map has loaded. A session key is a special Bing Maps key that marks requests to the REST services as non-billable.
4. When a custom share button is tapped show the UI for the Share charm.
5. Create an event handler for when the Share charm is launched. To share an image through the share charm, generate some HTML with the layout you prefer. Add an img tag for where you want the image to go and provide it with a temporary URL. You can then load the image as a stream to the request and specify the temporary URL the image is meant for. In the HTML you can also add an anchor tag that links to the Bing Maps consumer site with the same map, but interactive.
If you are using JavaScript you have one more task and that is to load the Bing Maps control.
If you are using C# open the MainPage.xaml.cs file and update the code to the following:
using System;
using Windows.ApplicationModel.DataTransfer;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
namespace BingMapsShareCharm
{
public sealed partial class MainPage : Page
{
/// <summary>
/// A reference to the DataTransferManager for the Share charm.
/// </summary>
private DataTransferManager dataTransferManager;
private string sessionKey;
public MainPage()
{
this.InitializeComponent();
//Get the DataTransferManager object associated with current window
dataTransferManager = DataTransferManager.GetForCurrentView();
MyMap.Loaded += MyMap_Loaded;
}
private async void MyMap_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
sessionKey = await MyMap.GetSessionIdAsync();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//Register the share handler event
dataTransferManager.DataRequested += ShareHandler;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
//Unregister the share handler event
dataTransferManager.DataRequested -= ShareHandler;
}
private void ShareLocation_Tapped(object sender, TappedRoutedEventArgs e)
{
//Show the charm bar with Share option opened
DataTransferManager.ShowShareUI();
}
private void ShareHandler(DataTransferManager sender, DataRequestedEventArgs e)
{
//A temporary image URL that is used for referencing the created map image.
string localImage = "ms-appx:///images/map.png";
//Use the Bing Maps REST Services to retrieve a static map image of the selected location.
string mapImageUrl = string.Format("https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/{0:N5},{1:N5}/{2}?mapSize=400,300&key={3}",
MyMap.Center.Latitude, MyMap.Center.Longitude, Math.Round(MyMap.ZoomLevel), sessionKey);
//Create URL to the Bing Maps consumer site
string bingMapsUrl = string.Format("https://bing.com/maps/default.aspx?v=2&cp={0:N5}~{1:N5}&lvl={2}",
MyMap.Center.Latitude, MyMap.Center.Longitude, Math.Round(MyMap.ZoomLevel));
//Handle the Share Charm request and insert HTML content.
DataRequest request = e.Request;
request.Data.Properties.Title = "Share Map";
request.Data.Properties.Description = "Share an image of the current map.";
request.Data.SetHtmlFormat(HtmlFormatHelper.CreateHtmlFormat(
string.Format("Map of: {0:N5}, {1:N5}<br/><br/><img src='{2}'/><br/><a href='{3}'>View on Bing Maps</a>",
MyMap.Center.Latitude, MyMap.Center.Longitude, localImage, bingMapsUrl)));
//Load the map image into the email as a stream.
RandomAccessStreamReference streamRef = RandomAccessStreamReference.CreateFromUri(new Uri(mapImageUrl));
request.Data.ResourceMap[localImage] = streamRef;
}
}
}
If you are using Visual Basic open the MainPage.xaml.vb file and update the code to the following:
Imports Windows.ApplicationModel.DataTransfer
Imports Windows.Storage.Streams
Imports Windows.UI.Xaml.Controls
Imports Windows.UI.Xaml.Input
Imports Windows.UI.Xaml.Navigation
Partial Public NotInheritable Class MainPage
Inherits Page
''' <summary>
''' A reference to the DataTransferManager for the Share charm.
''' </summary>
Private dataTransferManager As DataTransferManager
Private sessionKey As String
Public Sub New()
Me.InitializeComponent()
'Get the DataTransferManager object associated with current window
dataTransferManager = dataTransferManager.GetForCurrentView()
AddHandler MyMap.Loaded, AddressOf MyMap_Loaded
End Sub
Protected Async Sub MyMap_Loaded(sender As Object, e As Windows.UI.Xaml.RoutedEventArgs)
sessionKey = Await MyMap.GetSessionIdAsync()
End Sub
Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs)
'Register the share handler event
AddHandler dataTransferManager.DataRequested, AddressOf ShareHandler
End Sub
Protected Overrides Sub OnNavigatedFrom(e As NavigationEventArgs)
'Unregister the share handler event
RemoveHandler dataTransferManager.DataRequested, AddressOf ShareHandler
End Sub
Private Sub ShareLocation_Tapped(sender As Object, e As TappedRoutedEventArgs)
'Show the charm bar with Share option opened
dataTransferManager.ShowShareUI()
End Sub
Private Sub ShareHandler(sender As DataTransferManager, e As DataRequestedEventArgs)
'A temporary image URL that is used for referencing the created map image.
Dim localImage As String = "ms-appx:///images/map.png"
'Use the Bing Maps REST Services to retrieve a static map image of the selected location.
Dim mapImageUrl As String = String.Format("https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/{0:N5},{1:N5}/{2}?mapSize=400,300&key={3}", MyMap.Center.Latitude, MyMap.Center.Longitude, Math.Round(MyMap.ZoomLevel), sessionKey)
'Create URL to the Bing Maps consumer site
Dim bingMapsUrl As String = String.Format("https://bing.com/maps/default.aspx?v=2&cp={0:N5}~{1:N5}&lvl={2}",
MyMap.Center.Latitude, MyMap.Center.Longitude, Math.Round(MyMap.ZoomLevel))
'Handle the Share Charm request and insert HTML content.
Dim request As DataRequest = e.Request
request.Data.Properties.Title = "Share Map"
request.Data.Properties.Description = "Share an image of the current map."
request.Data.SetHtmlFormat(HtmlFormatHelper.CreateHtmlFormat(String.Format("Map of: {0:N5}, {1:N5}<br/><br/><img src='{2}'/><br/><a href='{3}'>View on Bing Maps</a>",
MyMap.Center.Latitude, MyMap.Center.Longitude, localImage, bingMapsUrl)))
'Load the map image into the email as a stream.
Dim streamRef As RandomAccessStreamReference = RandomAccessStreamReference.CreateFromUri(New Uri(mapImageUrl))
request.Data.ResourceMap(localImage) = streamRef
End Sub
End Class
If you are using JavaScript open the ShareMap.js file and update the code to the following:
(function () {
var app = WinJS.Application;
var map, sessionKey, dataTransferManager;
app.onready = function (args) {
//Get the DataTransferManager object associated with current window
dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
//Register the share handler event
dataTransferManager.addEventListener("datarequested", ShareHandler);
};
app.onunload = function (args) {
//Unregister the share handler event
dataTransferManager.removeEventListener("datarequested", ShareHandler);
};
function initialize() {
Microsoft.Maps.loadModule('Microsoft.Maps.Map', { callback: GetMap });
document.getElementById("ShareBtn").addEventListener("click", function (e) {
Windows.ApplicationModel.DataTransfer.DataTransferManager.showShareUI();
}, true);
}
function GetMap() {
map = new Microsoft.Maps.Map(document.getElementById("MyMap"), {
credentials: "YOUR_BING_MAPS_KEY"
});
map.getCredentials(function(c){
sessionKey = c;
});
}
function ShareHandler(e){
var mapCenter = map.getCenter();
var lat = Math.round(mapCenter.latitude * 100000) / 100000;
var lon = Math.round(mapCenter.longitude * 100000) / 100000;
//A temporary image URL that is used for referencing the created map image.
var localImage = "ms-appx:///images/map.png";
//Use the Bing Maps REST Services to retrieve a static map image.
var mapImageUrl = 'https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/' + lat + ',' + lon + '/' + map.getZoom() + '?mapSize=400,300&key=' + sessionKey;
//Create URL to the Bing Maps consumer site
var bingMapsUrl = 'https://bing.com/maps/default.aspx?v=2&cp=' + lat + '~' + lon + '&lvl=' + map.getZoom();
//Handle the Share Charm request and insert HTML content.
var request = e.request;
request.data.properties.title = 'Share Map';
request.data.properties.description = 'Share an image of the current map.';
var html = "Map of: " + lat + ", " + lon + "<br/><br/><img src='" + localImage + "'/><br/><a href='" + + "'>View on Bing Maps</a>";
request.data.setHtmlFormat(Windows.ApplicationModel.DataTransfer.HtmlFormatHelper.createHtmlFormat(html));
//Load the map image into the email as a stream.
var streamRef = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(new Windows.Foundation.Uri(mapImageUrl));
request.data.resourceMap[localImage] = streamRef;
}
document.addEventListener("DOMContentLoaded", initialize, false);
})();
Be sure to add your Bing Maps key into the GetMap method.
Now run your application, and zoom in to a location. Press the custom share button you created or the Share charm button and select the Mail option. You should end up with an email with a map in it. Here is a screenshot of the app:
I have made the full source code for all the languages available on the visual Studio galleries here.
Comments
- Anonymous
March 12, 2014
For fast responses to questions try using the Bing Maps forums: social.msdn.microsoft.com/.../home If you are creating a Windows Store app then take a look at my free eBook: rbrundritt.wordpress.com/my-book