UWP: New Controls (part 3 – Maps)
In this post I am going to talk about maps in Universal Windows Platform applications. And it’s better to start with the answer to the question that developers asked me many times: when will offline maps be available for Windows applications?
Starting with Windows 10 offline maps are available not just for phones but for desktops, laptops, tablets etc. User can visit Settings window and download all needed maps there. Once maps are downloaded the existing map control will use them by default.
It’s really cool because I can use my Windows 10 devices anywhere in order find addresses, the right direction etc. and you can use all these things directly from your application.
But offline maps are not the single feature of new Windows 10 maps. Let’s look at other features there:
- Unified platform – since Windows 10 you should not use several services like Here or Bing Maps for different tasks (or different services on different devices). All services are available under the same umbrella and can be used for any UWP applications;
- Adaptive interface – existing Maps application works fine on all devices. You can use touch, pen or mouse as well as use different screen sizes. The same we can say about MapControl which is available for developers;
- 2D view with business and traffic information – existing maps support all common features for 2D maps like different views, traffic information (you can on or off it), provide information about business locations and transit;
- Location – existing Maps application allows to find and display user location. Using Windows.Devices.Geolocation API you can find user location in your application in order to provide better user experience and implement lots of different tasks;
- External elements – developers can place own icons, rectangles, polygons and even XAML controls on maps. It allows to customize existing maps and extend the number of possible scenarios;
- Geofence – Geofencing API allows to notify application if user arrives to the defined area;
- Routing – developers can use Maps services that can calculate route to selected destination using different methods there (driving, walking);
- StreetSide – new functionality which allows to get images of the selected area to display it inside the interface. It’s very useful if user wants to understand what the selected area looks like;
- 3D views – one more new functionality which is available for developers starting with Windows 10: right now you can show maps not just in 2D but in 3D view modes. If 3D view is available for the selected area you can implement the same set of features like in standard Maps application;
It’s time to talk how to use maps in your applications. You have two ways there: you can redirect some user requests to the existing Maps application or you can integrate maps directly to your application.
If you are going to utilize existing Maps application you can redirect user to it using Launcher class. This class contains LaunchUriAsync static method which allows to open an external application using information from Uri. For example, if you use “http://....” in your uri then Launcher will open web browser but in case of Maps you need to start your uri with bingmaps: . Of course, it’s not enough and you need to pass some parameters using your uri. The full list of possible parameters you can find using the following link. For example, this code will open Maps application in move center to North Vancouver and zoom the map to level 14:
await Launcher.LaunchUriAsync(new Uri("bingmaps:?lvl=14&rpt=adr.North%20Vancouver%20BC"));
In order to start working with maps in your application you need to get “access key” visiting Maps Dev Center. You can select Trial key or Basic key based on your needs. Right after Windows 10 is released you will be able to find Universal Application in the list of possible applications but right now there is still no information about Windows 10. In any case you cannot publish Windows 10 applications right now (several days left), so you can use maps without key. It works fine but you will see the message that MapServiceToken is not specified and you cannot publish your application without MapServiceToken.
Once Windows 10 is available you can create Basic key for your universal application using the portal:
In order to start working with maps in your application you need to use three namespaces - Windows.UI.Xaml.Controls.Maps, Windows.Devices.Geolocation and Windows.Services.Maps and one control – MapControl. The first namespace contains MapControl itself and several classes which allows to place something on maps, setup camera and styles, prepare street view. The second namespace allows to get user location and contains Geofencing API as well. And the last one supports several utility classes which allows to find location by address, calculate route etc.
Because MapControl is not in default XAML namespaces you need to add a new namespace to XAML file:
And you are ready to use MapControl:
Right now we know how to add maps to your application and it’s time to see some tasks there.
Let’s start with basic functionality like how to center map, zoom map etc. Let’s have a look at the following code:
maps.ZoomLevel = 14; maps.Center = (await MapLocationFinder.FindLocationsAsync("North Vancouver, BC", null)).Locations.Point;
In this code we use reference to MapControl in order to assign two properties ZoomLevel and Center. Of course, in case of ZoomLevel you should not do anything special but if you want to center your map based on address you need to use map services – MapLocationFinder in this case. In my example I used FindLocationsAsync method and assigned the first location from the list to the Center property.
In order to apply 3D view to the maps you simply need to use Style attribute. It’s somewhat confusing because Style attributes exists for all UI controls and that can have different meaning.
<maps:MapControl Name="maps" Style="Aerial3D"/>
Of course, in case of the 3D View, it’s better to change default angle for map camera. You can do it usingthe static method of MapScene class called CreateFromLocationAndRadius. Thanks to this method you can create a scene using radius (meters), zoom level and radius (degrees). Once you have MapScene object you need to use TrySetSceneAsync method to apply the scene:
await maps.TrySetSceneAsync(MapScene.CreateFromLocationAndRadius((await MapLocationFinder.FindLocationsAsync("Vancouver Downtown, BC", null)).Locations.Point,500,90,60));
If you run my code you will see center of Vancouver in 3D:
So, applying 3D view is easy. The same works for the StreetView functionality. If you want to use the street view you need just two lines of code:
StreetsidePanorama panorama=await StreetsidePanorama.FindNearbyAsync((await MapLocationFinder.FindLocationsAsync("Vancouver Downtown, BC", null)).Locations.Point); maps.CustomExperience = new StreetsideExperience(panorama);
If you run this code you can see something like this:
Of course, existing maps show lots of different information but if you integrate maps to your application, probably, you want to add your own objects to maps.
The simplest objects which you can add to the maps are MapIcon, MapPolygon and MapPolyline. For example, if you want to add an icon to the maps you can run the following code:
MapIcon mapIcon = new MapIcon(); mapIcon.Location = maps.Center; mapIcon.NormalizedAnchorPoint = new Point(0.5, 1.0); mapIcon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/weather.png")); mapIcon.ZIndex = 0; maps.MapElements.Add(mapIcon);
You can use this code to place weather icons in the area, points of interest etc.
Additionally you can add XAML controls to the maps. In this case you need to use Children collection instead of MapElements as before. But it’s not enough to add XAML UI control, you need to place the control to the right position on the maps. In order to do it you can use the SetLocation method of the MapControl class. This method has two parameters: reference to added UI control and location.