SharePoint 2010 Bing Maps


Silverlight applications can be easily integrated with SharePoint 2010. SharePoint 2010 has a  Silverlight  webpart which takes the url of the xap file created from a silverlight application and shows it in the sharepoint 2010 pages. Let's create a Bing Map Silverlight application and integrate it with SharePoint 2010. Before we start download and install Bing Maps Silverlight Control SDK.


Open Visual Studio 2010 and create a Silverlight application. Name it BingMapInSharepoint as shown:


Next, either check or uncheck the check box: host the silverlight application in a new website.

Now add references to Bing Map and SahrePoint client asseblies.
Microsoft.Maps.MapControl
Microsoft.Maps.MapControl.Common
Microsoft.SharePoint.Client
Microsoft.SharePoint.Client.Runtime


Open MainPage.xaml and include the following namespace.

xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"

Replace the default grid with following implementation.

 <Grid x:Name="LayoutRoot" Background="White">


        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0" >
            <ComboBox MinWidth="150" Foreground="YellowGreen" Background="#555555" Width="300" Name="cmbLocation" />
            <Button Name="Search" MinWidth="100" MinHeight="30" Content="Search" Background="Black" Click="Search_Click">
            </Button>
        </StackPanel>
        <m:Map Name="BingMap" CredentialsProvider="Aj2xX8DulDVyS5NOkqjbl5MxradQTWal7UbJ08bVO6dFmA-W9U1kbWZ88yQB-usH"  AnimationLevel="Full"                         
                       Mode="AerialWithLabels"
                       ZoomLevel="3"
                       Center="20.000,77.000" Grid.Row="1">
            <m:Map.Children>
                <m:MapLayer x:Name="Pushpins"/>
            </m:Map.Children>
        </m:Map>
    </Grid>



Here we are creating a combo box which will contain the name of the locations retrieved from a sharepoint list .I have given my Bing Map key. You can use this for testing purpose or create your own key. The map will be centered at India by default as we have specified the co-ordinates of India.
Next open the MainPage.xaml.cs and add the following using statements:

using Microsoft.Maps.MapControl;
using BingMapInSharepoint.GeocodeService;
using Microsoft.SharePoint.Client;


Now let's create a service which will help us in finding the co-ordinates of the given locations. In "References" click on Add service reference.  Enter the url "http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc/mex" in the address and click on Go. Name the service as GeocodeService.





Copy the following code in MainPage.xaml.cs. This is used to identify a location and display a pushpin for the location.

private void Geocode(string strAddress, int waypointIndex)
        {
            // Create the service variable and set the callback method using the                    GeocodeCompleted property.
            GeocodeService.GeocodeServiceClient geocodeService = new             GeocodeService.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            geocodeService.GeocodeCompleted += new EventHandler<GeocodeService.GeocodeCompletedEventArgs>(geocodeService_GeocodeCompleted);

            // Set the credentials and the geocode query, which could be an address or location.
            GeocodeService.GeocodeRequest geocodeRequest = new GeocodeService.GeocodeRequest();
            geocodeRequest.Credentials = new Credentials();
            geocodeRequest.Credentials.ApplicationId = ((ApplicationIdCredentialsProvider)BingMap.CredentialsProvider).ApplicationId;
            geocodeRequest.Query = strAddress;

            // Make the asynchronous Geocode request, using the ‘waypoint index’ as
            //   the user state to track this request and allow it to be identified when the response is returned.
            geocodeService.GeocodeAsync(geocodeRequest, waypointIndex);
        }

        private void geocodeService_GeocodeCompleted(object sender, GeocodeService.GeocodeCompletedEventArgs e)
        {
            GeocodeResult result = null;
            if (e.Result.Results.Count > 0)
            {
                result = e.Result.Results[0];
                if (result != null)
                {
                    this.ShowPushpin(result);
                }
            }
        }

        private void ShowPushpin(GeocodeResult result)
        {
            GeocodeLocation gloc = result.Locations[0];
            Location location = new Location(gloc.Latitude, gloc.Longitude);
            Pushpin pushpin = new Pushpin();
            pushpin.Width = 7;
            pushpin.Height = 10;
            //pushpin.Tag = description;
            pushpin.Location = location;
            Pushpins.AddChild(pushpin, location, PositionOrigin.Center);
        }
 private void Search_Click(object sender, RoutedEventArgs e)
        {
            Geocode(cmbLocation.SelectedItem.ToString(), 0);
        }

Now copy following code, this will use client side object model to retrieve the name of the locations from a SharePoint list named Cities.
 Web oWebsite;

        IEnumerable<ListItem> listItems;
        private delegate void UpdateUIMethod();
        public MainPage()
        {
            InitializeComponent();
            ClientContext clientContext = ClientContext.Current;
            oWebsite = clientContext.Web;
            var oList = oWebsite.Lists.GetByTitle("Cities");
            CamlQuery camlQuery = new CamlQuery();
            IQueryable<ListItem> items = oList.GetItems(camlQuery);
            listItems = clientContext.LoadQuery(items);
            clientContext.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed);
        }

        private void onQuerySucceeded(object sender, ClientRequestSucceededEventArgs args)
        {
            UpdateUIMethod updateUI = DisplayInfo;
            this.Dispatcher.BeginInvoke(updateUI);
        }

        private void DisplayInfo()
        {
            foreach (ListItem oListItem in listItems)
            {
                cmbLocation.Items.Add(oListItem["Title"]);
            }
        }
        private void onQueryFailed(object sender, ClientRequestFailedEventArgs args)
        {
            MessageBox.Show("Request failed. " + args.Message + "\n" + args.StackTrace);
        }



The silverlight part is complete. Now add a SharePoint empty project to the solution and add a module element to it. Name the module BingMap as shown.




Delete the default sample.txt file created in a module. Right click on module and select properties. Click on Project Output References in the properties window and add the silverlight application to it. In our case the name of the silverlight application is BingMapInSharepoint. Select the deployment type to be Element File and Project Name as BingMapInSharepoint as shown:



The Elements.xm file in the module shoulg look like this now.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="BingMap">
  <File Path="BingMap\BingMapInSharepoint.xap" Url="BingMap/BingMapInSharepoint.xap" />
</Module>
</Elements>

That is it. Now right click on the SharePoint project and select deploy. After the project is deployed go to your SharePoint site. First, create a custom list name "Cities" and add the names of the few Indian  cities to it.



Now in order to make sure that the silverlight xap file has been properly deployed to our sharepoint side let us follow the given steps:
In my case the name of the site to which the solution was deployed is http://intranet.contoso.com. So If I type http://intranet/BingMap/BingMapInSharepoint.xap at the web address I will get the following message.



Once, you confirm that xap file has been deployed properly, go to a webpart page add a silverlight webpart to the page and specify the relative url of the xap file.


Finally, select some city from the drop down box and click on search button. A pushpin will appear at the city.