We will begin by building an application to work with the phone's location service, GeoCoordinateWatcher. The application, Bing Map Demo, is shown in Figure 1 and demonstrates the basic functions available through GeoCoordinateWatcher,
the location service that we introduced in the previous section. The
application will display your location with a blinking icon on a map and
continuously update your position as you move.
In this demo, when you click
the Start button, it will start the location service that will send
notification when the position is changed, and upon the changed position
event, the Bing Maps map will be updated with the new position. You can
actually start the application while you are walking and watch the
position of the locator (red dot) on the map change as you move.
You'll build the demo in
four steps. First, you need to register with the Bing Maps service
portal and then create a new Visual Studio project. Next you'll build
the project's user interface and finish up by adding code to respond to
commands from the user.
1. Registering with the Bing Maps Service Portal and Installing the Bing Maps SDK
Before you can use the Bing Maps Silverlight control and its service offerings, you must register with Bing Maps at www.bingmapsportal.com/.
Go to www.bingmapsportal.com/ and you should see something similar to Figure 2.
Click the Create button and follow the instructions provided by Microsoft.
Once
you create a Bing Maps service user, you must create an application key
so that you can use the Bing Maps control and the Bing Maps service
from Windows Phone. Sign in to the Bing Maps portal, and once you are
logged in, click the "Create or view keys" hyperlink as shown in Figure 3.
Once you've created the Bing Maps application key, you must install the Windows Phone SDK found at http://developer.windowsphone.com/windows-phone-7/.
If you successfully installed the Windows Phone SDK, the binaries (Microsoft.Phone.Controls.Maps) can be referenced from the project in order to use the Bing Maps Silverlight control.
.2. Creating the BingMapDemo Project
To set up the BingMapDemo project, follow the steps you've used for previous examples in this book:
Open Microsoft Visual Studio 2010 Express for Windows Phone on your workstation.
Create a new Windows Phone Application by selecting File =>
New Project on the Visual Studio command menu. Select the Windows Phone
Application template, and name the application "BingMapDemo."
In order to use Bing Maps control in Windows Phone, you must reference Microsoft.Phone.Controls.Maps, and in order to track your movement, you need to add reference to System.Device
to use the location service. Open Solution Explorer and add those
references now. Check to ensure that your list of references matches the
list shown in Figure 4.
3. Coding the User Interface
Now it's time to code the user
interface, which we've chosen to implement in XAML. Sometimes it is
faster to work with XAML when working with a simple example that
requires only a few controls. Go to Solution Explorer, open MainPage.xaml, and replace the XAML you find there with the following two blocks of code.
3.1. Declaring the UI Resources
Most of the namespaces you
see in this snippet are typically declared by default when you first
create a Windows Phone project. The following namespace is unique to
this application and allows you to add the Bing Maps control you will
use to plot your location: xmlns:BingMap="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps".
<phone:PhoneApplicationPage
x:Class="BingMapDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:BingMap=
"clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps
"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
shell:SystemTray.IsVisible="True">
3.2. Building the Main Page and Adding a Bing Maps Control
To the main page, you will be
adding a Bing Maps control to display your position and a button to
start the location service. You'll also add an animation storyboard
named BlinkLocator to cause the locator icon to blink by changing its
color. Notice that inside bingMap control there is a BingMap:Pushpin named bingMapLocator. The map layer bingMapLocator contains an Ellipse control named locator,
whose initial map position in latitude and longitude is (0, 0). In this
application, the location service will provide changing positions in
the latitude and longitude so that the locator
position can be properly updated. This is a very simple but very
powerful demonstration of using the location service and Bing Maps
control. You can use the same technique for Yahoo or Google Maps, as
their API is very similar to Bing Maps.
<phone:PhoneApplicationPage.Resources>
<Storyboard x:Name="BlinkLocator" AutoReverse="True" RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
Storyboard.TargetName="locator">
<EasingColorKeyFrame KeyTime="0" Value="Red"/>
<EasingColorKeyFrame KeyTime="0:0:1" Value="#FFCEFF00"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
<TextBlock x:Name="ApplicationTitle" Text="Bing Map Demo"
Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
<Grid x:Name="ContentGrid" Grid.Row="1">
<BingMap:Map Name="bingMap" NavigationVisibility="Collapsed"
Margin="0,0,0,72">
<BingMap:Pushpin Name="bingMapLocator">
<BingMap:Pushpin.Content>
<Ellipse Fill="Red" Width="20" Height="20"
BingMap:MapLayer.Position="0,0"
Name="locator" />
<BingMap:Pushpin.Content>
</BingMap: Pushpin>
</BingMap:Map>
<Button Content="Start" Height="72" HorizontalAlignment="Right"
Margin="0,633,0,0" Name="btnStart" VerticalAlignment="Top" Width="160"
Click="btnStart_Click" />
<TextBlock Height="30" HorizontalAlignment="Left" Margin="6,657,0,0"
Name="txtStatus" Text="Status" VerticalAlignment="Top" Width="308" />
</Grid>
</Grid>
</phone:PhoneApplicationPage>
Notice here that we changed the content of the Pushpin, which is the locator that specifies where you are. You can add any type of control and change the appearance of the Pushpin. You can even put a placeholder and dynamically change the content of the Pushpin.
|
|
Once you have loaded the XAML code, you should see the layout shown in Figure 5.
In the next section, you will be adding an event to consume the GPS
data and then to plot the data onto the map layer of the Bing Maps
Silverlight control.
4. Coding the Application
In Solution Explorer, open MainPage.xaml.cs and replace the code there with the following C# code blocks, which will implement the media player's functionalities.
4.1. Specifying the Namespaces
Begin by listing the namespaces the application will use. Notice the inclusion of Microsoft.Maps.Control, which will allow you to manipulate Bing Maps control, and System.Device, which will allow you to work with geoCoordinateWatcher, which will retrieve the location data from GPS, Wi-Fi, or cellular towers.
using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Maps.MapControl;
using System.Device.Location;
namespace BingMapDemo
{
public partial class MainPage : PhoneApplicationPage
{
4.2. Initializing Variables
The variable _geoCoordinateWatcher
is an instance of the location service class that you'll use to access
and retrieve location data. Notice that you will be using GeoPositionAccuracy.High,
which will use the phone device's GPS, and for this to work you must
use the real Windows Phone device. Also here you will be setting MovementThreshold
to 100 meters so that the PositionChanged event fires every 100 meters,
and you will be plotting your current location on the Bing Maps map.
GeoCoordinateWatcher has StatusChanged and PositionChanged events that notify the application whenever the new updated position is received from the GPS.
As for bingMap, you
will hide the Microsoft Bing Maps logo and copyright in order to make
things cleaner and make more space for other controls for the
application. Finally, in order to use the map control at all, you must
set ClientTokenCredentialsProvider to the value of the application key you obtained when you registered at the Bing Maps site.
GeoCoordinateWatcher _geoCoordinateWatcher;
public MainPage()
{
InitializeComponent();
// Add your own BingMap Key
bingMap.CredentialsProvider =
new ApplicationIdCredentialsProvider("ADD-YOUR-OWN-KEY");
// Remove Bing Maps logo and copyrights in order to gain
// extra space at the bottom of the map
bingMap.LogoVisibility = Visibility.Collapsed;
bingMap.CopyrightVisibility = Visibility.Collapsed;
// Delcare GeoCoordinateWatcher with high accuracy
// in order to use the device's GPS
_geoCoordinateWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
_geoCoordinateWatcher.MovementThreshold = 100;
// Subscribe to the device's status changed event
_geoCoordinateWatcher.StatusChanged +=
new EventHandler<GeoPositionStatusChangedEventArgs>(
_geoCoordinateWatcher_StatusChanged);
// Subscribe to the device's position changed event
// to receive GPS coordinates (longitude and latitude)
_geoCoordinateWatcher.PositionChanged +=
New EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(
_geoCoordinateWatcher_PositionChanged);
}
4.3. Responding to StatusChanged and PositionChanged GeoCoordinateWatcher Events
In GeoCoordinateWatcher, StatusChanged fires when the GPS status changes and PositionChanged fires when the GPS receives new a position. In StatusChanged, if the received status is Disabled,
you must notify the user that the device's location service is disabled
and must be turned on. You can enable the location service on the
device by going to Settings => Location => Turn on the location service.
Note here that the PositionChanged event will not fire until the position of the phone has changed by at least 100 meters as specified by MovementThreshold. When the StatusChanged event fires, txtStatus will be updated, and when the PositionChanged event fires, the locator icon you have added to the Bing Maps layer will be moved accordingly.
private void _geoCoordinateWatcher_PositionChanged(object sender,
GeoPositionChangedEventArgs<GeoCoordinate> e)
{
Deployment.Current.Dispatcher.BeginInvoke(() => ChangePosition(e));
}
private void ChangePosition(GeoPositionChangedEventArgs<GeoCoordinate> e)
{
SetLocation(e.Position.Location.Latitude,
e.Position.Location.Longitude, 10, true);
}
private void _geoCoordinateWatcher_StatusChanged(object sender,
GeoPositionStatusChangedEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() => StatusChanged(e));
}
private void StatusChanged(GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Disabled:
txtStatus.Text = "Location Service is disabled!";
break;
case GeoPositionStatus.Initializing:
txtStatus.Text = "Initializing Location Service...";
break;
case GeoPositionStatus.NoData:
txtStatus.Text = "Your position could not be located.";
break;
case GeoPositionStatus.Ready:
break;
}
}
4.4. Starting the Location Service: GeoCoordinateWatcher
When the user clicks the Start button, the location service will be started. TryStart will return false
if the phone's location service is disabled. If the location service is
disabled, a message box is displayed to the user, instructing the user
to enable the location service on the phone.
private void btnStart_Click(object sender, RoutedEventArgs e)
{
if (!_geoCoordinateWatcher.TryStart(true, TimeSpan.FromSeconds(5)))
{
MessageBox.Show("Please enable Location Service on the Phone.",
"Warning", MessageBoxButton.OK);
}
}
4.5. Plotting the Location on the Bing Maps MapLayer
BingMap has a SetView method that allows you to set the current view on the screen using the location data, latitude and longitude, received from GeoCoordinateWatcher. The zoomLevel property indicates how far into the location the map will be zoomed. BingMap also has MapLayer, which can set the position of the map layer with respect to the received location. To make things interesting, we animated bingMapLocator with simple color blinks.
private void SetLocation(double latitude, double longitude,
double zoomLevel, bool showLocator)
{
Location location = new Location(latitude, latitude);
bingMap.SetView(location, zoomLevel);
MapLayer.SetPosition(locator, location);
if (showLocator)
{
locator.Visibility = Visibility.Visible;
BlinkLocator.Begin();
}
else
{
locator.Visibility = Visibility.Collapsed;
BlinkLocator.Stop();
}
}
}
}
5. Testing the Finished Application
To test the application, press F5. The result should resemble Figure 1
on the phone device. Remember that you must have a real phone device to
be able to use real GPS. In the following section, we will utilize Bing
Maps geocoding service to convert the address into geocode of longitude
and latitude in order to plot the address on the Bing Maps Silverlight
control.