Silverlight Bing Maps Control and Drag & Drop
Hello All,
I was recently asked to build up a Silverlight tool to show a file full of addresses on a map. I decided to use the Silverlight bing maps control and I must say I was not disappointed with it's functionality. It ended up being extremely simple. The tools used to create this were VS2010, Silverlight 4, Bing maps Silverlight control, and the Bing maps web services.
Setting up the Bing Maps account:
All you need is a live account and your good to go: https://www.bingmapsportal.com/. Log in with your Live ID and enter your app name and URL and the keys are in the ignition!
Get the Bing Maps Control:
Grab it from: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=beb29d27-6f0c-494f-b028-1e0e3187e830. Install that bad boy and create your Silverlight app in VS2010.
Adding the Map Control to your app:
<UserControl x:Class="PeopleMap.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" AllowDrop="True">
<Grid x:Name="LayoutRoot" Background="White">
<m:Map x:Name="myMap" CredentialsProvider="Your Key!!" Mode="Road"/>
</Grid>
</UserControl>
Make sure to mark the user control from your main view to allow drop. I’m expecting a file with each address on the new line.
Add in the reference to the Bing Geocoding services to your Silverlight project:
Add in a Service Reference to your Silverlight project with the following URL: http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc. I used the namespace of “BingGeocode”.
Add in code to handle the Geocode / location calls and throw some pins onto your map:
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Maps.MapControl;
using PeopleMap.BingGeocode;
namespace PeopleMap
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
Drop += MainPage_Drop;
}
private void MainPage_Drop(object sender, DragEventArgs e)
{
if (e.Data != null)
{
var files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
var firstFile = files.IfNotNull(i => i.FirstOrDefault());
firstFile.IfNotNull(i =>
{
using (var streamReader = firstFile.OpenText())
{
while (!streamReader.EndOfStream)
{
RequestAddress(streamReader.ReadLine());
}
}
});
}
}
private void RequestAddress(string lineText)
{
var geocodeRequest = new GeocodeRequest { Query = lineText };
var geocodeClient = new GeocodeServiceClient();
geocodeRequest.Credentials = new Credentials
{
ApplicationId =
((ApplicationIdCredentialsProvider) myMap.CredentialsProvider).
ApplicationId
};
geocodeClient.GeocodeCompleted += GeocodeClientGeocodeCompleted;
geocodeClient.GeocodeAsync(geocodeRequest);
}
private void GeocodeClientGeocodeCompleted(object sender, GeocodeCompletedEventArgs e)
{
if(e.Error == null)
{
var firstResult = e.Result.Results.FirstOrDefault();
if (firstResult != null)
{
var location = firstResult.Locations.FirstOrDefault();
var pin = new Pushpin {Location = location};
pin.SetValue(ToolTipService.ToolTipProperty, new TextBlock{Text = firstResult.DisplayName});
myMap.Children.Add(pin);
}
}
else
{
throw new Exception(e.Error.Message);
}
}
}
}
Useful extension methods used:
I end up using these in a bunch of my little projects to do things in line, rather than writing longer code. I think they are more readable. I hope they help you.
using System;
namespace PeopleMap
{
public static class Extenstions
{
public static TResult IfNotNull<TArg, TResult>(this TArg obj, Func<TArg, TResult> func) where TArg : class
{
return obj != null ? func(obj) : default(TResult);
}
public static void IfNotNull<TArg>(this TArg obj, Action<TArg> action) where TArg : class
{
if (obj != null)
action(obj);
}
}
}
My input (just create a txt file with the following addresses on their own lines – if you don’t like Cleveland, insert your own data):
50 Public Square, Cleveland, OH
1100 Rock and Roll Blvd., Cleveland, OH
1085 West 3rd Street, Cleveland, OH
1 Center Court, Cleveland, OH
That’s about it. The solution was very simple, but very useful. All you have to do, is drop the file on the window, and you have your data show up on the map.
If you like this, you will probably like the information coming from my twitter account.
Cheers,
David Justice