Mobile Corner

Mapping and Location in Windows Phone

Using Windows Phone's Map control and displaying multiple points using data binding.

A previous article demonstrated how to retrieve location information from a Windows Phone using the GeoCoordinateWatcher, and how to present this information within your application using the Bing Map control. We're going to extend this example to show how to wire up a collection of points, and how you can customize how each of these points are displayed.

To begin with, we need some data to display. In this case, the data set (Listing 1) is a static array of Australia's capital cities.

As this is a static array of CapitalCity items, we could simply add the correct number of PushPins to the Map control and connect them to the relevant index of the Cities array. However, this wouldn't work so well if instead the array was a collection that could dynamically change. As such, we want a method for automatically adding the correct number of PushPins to the Map. We could do this in code by iterating through the Cities array and manually creating an instance of the PushPin control and adding it to the Map control. While this option can be good for performance, it makes it very hard to design what each PushPin will look like at design time.

The solution to this problem is to data bind the Cities array to an instance of the MapItemsControl, which is added to the Map control. The XAML in Listing 2 includes a MapItemsControl which is data bound to the Cities property. Each CapitalCity is displayed using the CityItemTemplate, which shows the Name of the city over the top of an Image.

If you run the application at this point, you'll notice that the Map starts off completely zoomed out with the cities located off to the right side. This can easily be adjusted by setting the ZoomLevel and the Center of the map. In this case we're going to set the initial ZoomLevel to 3 and the Center of the map to be the average of the CapitalCity locations.

public GeoCoordinate CenterOfCities
{
    get
    {
        return new GeoCoordinate(
                   Cities.Average(c=>c.Location.Latitude),
                   Cities.Average(c=>c.Location.Longitude));
    }
}

If you're using this sample on a real device, you may notice a couple of things: It may take awhile for the device to report your location or your location may be inaccurate, and your location may appear to jump around. The first two are related to the desired accuracy you may have set when creating the instance of the GeoCoordinateWatcher. If you set the desired accuracy to High (see following code), it may take longer for the device to report your current location, but it will be more accurate.

This location jumping around is related to location information being returned by different sensors (GPS, cell network and WiFi) with varying levels of accuracy. To reduce this effect, you can set the MovementThreshold property to the minimum number of meters through which the location has to change in order for the device to report a change.

watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
watcher.MovementThreshold = 50;

Finally, we're going to add the ability to get directions from the user's current location to the CapitalCity they've tapped. We need to add an event handler to the Tap event for the PushPin, and from there we'll call out to the BingMapDirectionsTask to illustrate the directions on how to get to that city. First, the XAML for the DataTemplate for each CapitalCity needs to include the Tap event handler.

<DataTemplate x:Key="CityItemTemplate">
   <maps:Pushpin Location="{Binding Location}" Tap="CityTapped">
       <Grid MaxHeight="30" MaxWidth="80">
           <Image Source="{Binding ImageUrl}" Stretch="UniformToFill"/>
           <TextBlock Text="{Binding Name}" Foreground="Black" />
       </Grid>
   </maps:Pushpin>
</DataTemplate>

Next, the code for the Tap event handler, which retrieves the current location (as currently displayed on the map); determines which CaptialCity was tapped; and invokes the BingMapsDirectionsTask with the appropriate Start and End values.

private void CityTapped(object sender, GestureEventArgs e)
{
    var currentLocation = MyLocationPushPin.Location;
    var city = (sender as Pushpin).DataContext as CapitalCity;
    var bingTask = new BingMapsDirectionsTask()
                        {
                Start = new LabeledMapLocation("Current Location", currentLocation),
                End = new LabeledMapLocation(city.Name, city.Location)
                        };
    bingTask.Show();
}

It's worth noting that there is also a BingMapsTask, which is useful for showing a single location via the Maps application on the Windows Phone. This includes the ability to invoke Scout, which can show nearby locations like restaurants and places of interest. Figure 1 shows the cities and current location (left image), the BingMapsDirectionsTask (center image) and finally Scout in action (right image).


[Click on image for larger view.]
Figure 1. Mapping cities and directions.
In this article we've covered another scenario for using the Map control and how you can display multiple points using data binding. You've also seen some of the additional properties you can set on both the GeoCoordinateWatcher and the Map Control in order to customize how your application behaves.

About the Author

Nick Randolph runs Built to Roam, a consulting company that specializes in training, mentoring and assisting other companies build mobile applications. With a heritage in rich client applications for both the desktop and a variety of mobile platforms, Nick currently presents, writes and educates on the Windows Phone platform.

comments powered by Disqus

Featured

  • Mastering Blazor Authentication and Authorization

    At the Visual Studio Live! @ Microsoft HQ developer conference set for August, Rockford Lhotka will explain the ins and outs of authentication across Blazor Server, WebAssembly, and .NET MAUI Hybrid apps, and show how to use identity and claims to customize application behavior through fine-grained authorization.

  • Linear Support Vector Regression from Scratch Using C# with Evolutionary Training

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the linear support vector regression (linear SVR) technique, where the goal is to predict a single numeric value. A linear SVR model uses an unusual error/loss function and cannot be trained using standard simple techniques, and so evolutionary optimization training is used.

  • Low-Code Report Says AI Will Enhance, Not Replace DIY Dev Tools

    Along with replacing software developers and possibly killing humanity, advanced AI is seen by many as a death knell for the do-it-yourself, low-code/no-code tooling industry, but a new report belies that notion.

  • Vibe Coding with Latest Visual Studio Preview

    Microsoft's latest Visual Studio preview facilitates "vibe coding," where developers mainly use GitHub Copilot AI to do all the programming in accordance with spoken or typed instructions.

  • Steve Sanderson Previews AI App Dev: Small Models, Agents and a Blazor Voice Assistant

    Blazor creator Steve Sanderson presented a keynote at the recent NDC London 2025 conference where he previewed the future of .NET application development with smaller AI models and autonomous agents, along with showcasing a new Blazor voice assistant project demonstrating cutting-edge functionality.

Subscribe on YouTube