Using the REST and Spatial Data Services
The Bing Maps REST Services and Bing Spatial Data Services provide functionality such as geocoding, points of interest (POI) searches, and routing that you can add to your Bing Maps WPF Control application. This topic shows how to create a simple application that performs a POI search and displays the results on a map.
The application performs this task by using the following steps:
User inputs a location and distance from that location to search.
Bing Maps REST Services Locations API is used to geocode the location.
Bing Spatial Data Services Query API is used to search for points of interest near the location.
The POI information is displayed and pushpins are added to the map.
The following sections describe parts of the application. The complete code sample is also provided.
User Interface
The following XAML code provides controls for the user to select a POI type, input a location and select a distance to search. It also sets up the framework for displaying the POI information and the map.
<Window x:Class="RESTandWPFwithXML.MainWindow"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
Title="MainWindow"
Height="500" Width="800">
<Window.Resources>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<Style x:Key="BlueLabel" TargetType="Label" BasedOn="{StaticResource LabelStyle}">
<Setter Property="Foreground" Value="#FF0E6EDC"/>
</Style>
<Style x:Key="RedLabel" TargetType="Label" BasedOn="{StaticResource LabelStyle}">
<Setter Property="Foreground" Value="#FFA42E2E"/>
</Style>
<Style x:Key="AddressStyle" TargetType="Label" >
<Setter Property="Padding" Value="10px 0 0 0"/>
<Setter Property="Margin" Value="0 0 0 0" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="115"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas Name="SearchParameters" Grid.Row="0" Grid.ColumnSpan="2" Margin="0,0,36,0">
<Label Style="{StaticResource RedLabel}" >Search and Map Entities Near a Location</Label>
<Label Canvas.Left="0" Canvas.Top="24" Foreground="#FF0E6EDC" AllowDrop="True" FontWeight="Bold" Content="Search for"></Label>
<Label Style="{StaticResource LabelStyle}" AllowDrop="True" Canvas.Left="0" Canvas.Top="49"
Content="Within" FontWeight="Bold" Foreground="#FF0E6EDC" />
<ComboBox Canvas.Left="50" Name="Distance" Canvas.Top="53" Height="20" >
<ComboBoxItem IsSelected="True">1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>5</ComboBoxItem>
</ComboBox>
<TextBox Height="25" Name="SearchNearby" Width="175" Text="Insert location" Canvas.Left="138" Canvas.Top="52" />
<Label Style="{StaticResource BlueLabel}" Canvas.Left="90" Canvas.Top="49" Content="km of " Height="28" Name="label1" />
<Button Click="Search_Click" Width="59" Height="24" Grid.ColumnSpan="2" Margin="0,77,251,39" HorizontalAlignment="Right" Canvas.Left="319" Canvas.Top="-25">Search</Button>
<ComboBox Name="EntityType" Canvas.Left="73" Canvas.Top="29" Height="21" Width="117" >
<ComboBoxItem Tag="7011" IsSelected="True">Hotel</ComboBoxItem>
<ComboBoxItem Tag="5800">Restaurant</ComboBoxItem>
<ComboBoxItem Tag="7999">Tourist Attraction</ComboBoxItem>
</ComboBox>
</Canvas>
<StackPanel Grid.Row="1" Grid.Column="0">
<Label Name="ErrorMessage" Visibility="Collapsed" ></Label>
<ScrollViewer Name="SearchResults" Visibility="Collapsed" Height="300">
<StackPanel Name="AddressList" ></StackPanel>
</ScrollViewer>
</StackPanel>
<StackPanel Grid.Row="1"
Grid.Column="1" >
<m:Map Visibility="Hidden" x:Name="myMap"
CredentialsProvider="Insert_Your_Bing_Maps_Key" Height="300" Width="300" />
<Label Name="myMapLabel" Visibility="Hidden" HorizontalAlignment="Center" >Use + and - to zoom in and out</Label>
</StackPanel>
</Grid>
</Window>
Geocoding using the REST Services
The following code-behind method creates a Bing Maps REST Services Find a Location by Query request to geocode (get the latitude and longitude coordinates) of the location requested by the user. The response contains one or more locations. The application chooses the top location for the POI search.
// Geocode an address and return a latitude and longitude
public XmlDocument Geocode(string addressQuery)
{
//Create REST Services geocode request using Locations API
string geocodeRequest = "http://dev.virtualearth.net/REST/v1/Locations/" + addressQuery + "?o=xml&key=" + BingMapsKey;
//Make the request and get the response
XmlDocument geocodeResponse = GetXmlResponse(geocodeRequest);
return (geocodeResponse);
}
' Geocode an address and return a latitude and longitude
Public Function Geocode(ByVal addressQuery As String) As XmlDocument
'Create REST Services geocode request using Locations API
Dim geocodeRequest As String = "http://dev.virtualearth.net/REST/v1/Locations/" & addressQuery & "?o=xml&key=" & BingMapsKey
'Make the request and get the response
Dim geocodeResponse As XmlDocument = GetXmlResponse(geocodeRequest)
Return (geocodeResponse)
End Function
This code-behind method is used to submit both Bing Maps REST Services and Bing Spatial Data Services requests and retrieve an XML response.
// Submit a REST Services or Spatial Data Services request and return the response
private XmlDocument GetXmlResponse(string requestUrl)
{
System.Diagnostics.Trace.WriteLine("Request URL (XML): " + requestUrl);
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format("Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(response.GetResponseStream());
return xmlDoc;
}
}
' Submit a REST Services or Spatial Data Services request and return the response
Private Function GetXmlResponse(ByVal requestUrl As String) As XmlDocument
System.Diagnostics.Trace.WriteLine("Request URL (XML): " & requestUrl)
Dim request As HttpWebRequest = TryCast(WebRequest.Create(requestUrl), HttpWebRequest)
Using response As HttpWebResponse = TryCast(request.GetResponse(), HttpWebResponse)
If response.StatusCode <> HttpStatusCode.OK Then
Throw New Exception(String.Format("Server error (HTTP {0}: {1}).", response.StatusCode, response.StatusDescription))
End If
Dim xmlDoc As New XmlDocument()
xmlDoc.Load(response.GetResponseStream())
Return xmlDoc
End Using
End Function
Searching for POI using the Spatial Data Services
The following code-behind method extracts the top location from the REST Services geocode response, and then uses it to create a Bing Spatial Data Services Query by Area request to search the NAVTEQNA data source for points of interest near the specified location. XPath queries are used to extract information from the responses. To use XPath queries with the Bing Maps REST Services, you must create an XmlNamespaceManager and add the URL for the REST Services data schema.
//Search for POI near a point
private void FindandDisplayNearbyPOI(XmlDocument xmlDoc)
{
//Get location information from geocode response
//Create namespace manager
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("rest", "https://schemas.microsoft.com/search/local/ws/rest/v1");
//Get all locations in the response and then extract the coordinates for the top location
XmlNodeList locationElements = xmlDoc.SelectNodes("//rest:Location", nsmgr);
if (locationElements.Count == 0)
{
ErrorMessage.Visibility = Visibility.Visible;
ErrorMessage.Content = "The location you entered could not be geocoded.";
}
else
{
//Get the geocode points that are used for display (UsageType=Display)
XmlNodeList displayGeocodePoints =
locationElements[0].SelectNodes(".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()", nsmgr);
string latitude = displayGeocodePoints[0].SelectSingleNode(".//rest:Latitude", nsmgr).InnerText;
string longitude = displayGeocodePoints[0].SelectSingleNode(".//rest:Longitude", nsmgr).InnerText;
ComboBoxItem entityTypeID = (ComboBoxItem)EntityType.SelectedItem;
ComboBoxItem distance = (ComboBoxItem)Distance.SelectedItem;
//Create the Bing Spatial Data Services request to get nearby POI
string findNearbyPOIRequest = "http://spatial.virtualearth.net/REST/v1/data/f22876ec257b474b82fe2ffcb8393150/NavteqNA/NavteqPOIs?spatialfilter=nearby("
+ latitude + "," + longitude + "," + distance.Content + ")"
+ "&$filter=EntityTypeID%20EQ%20'" + entityTypeID.Tag + "'&$select=EntityID,DisplayName,__Distance,Latitude,Longitude,AddressLine,Locality,AdminDistrict,PostalCode&$top=10"
+ "&key=" + BingMapsKey;
//Submit the Bing Spatial Data Services request and retrieve the response
XmlDocument nearbyPOI = GetXmlResponse(findNearbyPOIRequest);
//Center the map at the geocoded location and display the results
myMap.Center = new Location(Convert.ToDouble(latitude), Convert.ToDouble(longitude));
myMap.ZoomLevel = 12;
DisplayResults(nearbyPOI);
}
}
'Search for POI near a point
Private Sub FindandDisplayNearbyPOI(ByVal xmlDoc As XmlDocument)
'Get location information from geocode response
'Create namespace manager
Dim nsmgr As New XmlNamespaceManager(xmlDoc.NameTable)
nsmgr.AddNamespace("rest", "https://schemas.microsoft.com/search/local/ws/rest/v1")
'Get all locations in the response and then extract the coordinates for the top location
Dim locationElements As XmlNodeList = xmlDoc.SelectNodes("//rest:Location", nsmgr)
If locationElements.Count = 0 Then
ErrorMessage.Visibility = Visibility.Visible
ErrorMessage.Content = "The location you entered could not be geocoded."
Else
'Get the geocode points that are used for display (UsageType=Display)
Dim displayGeocodePoints As XmlNodeList = locationElements(0).SelectNodes(".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()", nsmgr)
Dim latitude As String = displayGeocodePoints(0).SelectSingleNode(".//rest:Latitude", nsmgr).InnerText
Dim longitude As String = displayGeocodePoints(0).SelectSingleNode(".//rest:Longitude", nsmgr).InnerText
Dim entityTypeID As ComboBoxItem = CType(EntityType.SelectedItem, ComboBoxItem)
Dim distance As ComboBoxItem = CType(Distance.SelectedItem, ComboBoxItem)
'Create the Bing Spatial Data Services request to get nearby POI
Dim findNearbyPOIRequest As String = "http://spatial.virtualearth.net/REST/v1/data/f22876ec257b474b82fe2ffcb8393150/NavteqNA/NavteqPOIs?spatialfilter=nearby(" & latitude & "," & longitude & "," & distance.Content & ")" & "&$filter=EntityTypeID%20EQ%20'" & entityTypeID.Tag & "'&$select=EntityID,DisplayName,__Distance,Latitude,Longitude,AddressLine,Locality,AdminDistrict,PostalCode&$top=10" & "&key=" & BingMapsKey
'Submit the Bing Spatial Data Services request and retrieve the response
Dim nearbyPOI As XmlDocument = GetXmlResponse(findNearbyPOIRequest)
'Center the map at the geocoded location and display the results
myMap.Center = New Location(Convert.ToDouble(latitude), Convert.ToDouble(longitude))
myMap.ZoomLevel = 12
DisplayResults(nearbyPOI)
End If
End Sub
Displaying the POI information
The following code-behind method uses XPath queries to retrieve and display the name and address information for each POI that is returned. In addition, pushpins for each POI are added to the map. The XAML structures that display this content are made visible during this step.
//Show the POI address information and insert pushpins on the map
private void DisplayResults(XmlDocument nearbyPOI)
{
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nearbyPOI.NameTable);
nsmgr.AddNamespace("d", "https://schemas.microsoft.com/ado/2007/08/dataservices");
nsmgr.AddNamespace("m", "https://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
nsmgr.AddNamespace("a", "http://www.w3.org/2005/Atom");
//Get the the entityID for each POI entity in the response
XmlNodeList displayNameList = nearbyPOI.SelectNodes("//d:DisplayName", nsmgr);
//Provide entity information and put a pushpin on the map.
if (displayNameList.Count == 0)
{
ErrorMessage.Content = "No results were found for this location.";
ErrorMessage.Visibility = Visibility.Visible;
}
else
{
XmlNodeList addressLineList = nearbyPOI.SelectNodes("//d:AddressLine", nsmgr);
XmlNodeList localityList = nearbyPOI.SelectNodes("//d:Locality", nsmgr);
XmlNodeList adminDistrictList = nearbyPOI.SelectNodes("//d:AdminDistrict", nsmgr);
XmlNodeList postalCodeList = nearbyPOI.SelectNodes("//d:PostalCode", nsmgr);
XmlNodeList latitudeList = nearbyPOI.SelectNodes("//d:Latitude", nsmgr);
XmlNodeList longitudeList = nearbyPOI.SelectNodes("//d:Longitude", nsmgr);
for (int i = 0; i < displayNameList.Count; i++)
{
AddLabel(AddressList, "[" + Convert.ToString(i + 1) + "] " + displayNameList[i].InnerText);
AddLabel(AddressList, addressLineList[i].InnerText);
AddLabel(AddressList, localityList[i].InnerText + ", " + adminDistrictList[i].InnerText);
AddLabel(AddressList, postalCodeList[i].InnerText);
AddLabel(AddressList, "");
AddPushpinToMap(Convert.ToDouble(latitudeList[i].InnerText), Convert.ToDouble(longitudeList[i].InnerText), Convert.ToString(i + 1));
}
SearchResults.Visibility = Visibility.Visible;
myMap.Visibility = Visibility.Visible;
myMapLabel.Visibility = Visibility.Visible;
myMap.Focus(); //allows '+' and '-' to zoom the map
}
}
'Show the POI address information and insert pushpins on the map
Private Sub DisplayResults(ByVal nearbyPOI As XmlDocument)
Dim nsmgr As New XmlNamespaceManager(nearbyPOI.NameTable)
nsmgr.AddNamespace("d", "https://schemas.microsoft.com/ado/2007/08/dataservices")
nsmgr.AddNamespace("m", "https://schemas.microsoft.com/ado/2007/08/dataservices/metadata")
nsmgr.AddNamespace("a", "http://www.w3.org/2005/Atom")
'Get the the entityID for each POI entity in the response
Dim displayNameList As XmlNodeList = nearbyPOI.SelectNodes("//d:DisplayName", nsmgr)
'Provide entity information and put a pushpin on the map.
If displayNameList.Count = 0 Then
ErrorMessage.Content = "No results were found for this location."
ErrorMessage.Visibility = Visibility.Visible
Else
Dim addressLineList As XmlNodeList = nearbyPOI.SelectNodes("//d:AddressLine", nsmgr)
Dim localityList As XmlNodeList = nearbyPOI.SelectNodes("//d:Locality", nsmgr)
Dim adminDistrictList As XmlNodeList = nearbyPOI.SelectNodes("//d:AdminDistrict", nsmgr)
Dim postalCodeList As XmlNodeList = nearbyPOI.SelectNodes("//d:PostalCode", nsmgr)
Dim latitudeList As XmlNodeList = nearbyPOI.SelectNodes("//d:Latitude", nsmgr)
Dim longitudeList As XmlNodeList = nearbyPOI.SelectNodes("//d:Longitude", nsmgr)
For i As Integer = 0 To displayNameList.Count - 1
AddLabel(AddressList, "[" & Convert.ToString(i + 1) & "] " & displayNameList(i).InnerText)
AddLabel(AddressList, addressLineList(i).InnerText)
AddLabel(AddressList, localityList(i).InnerText & ", " & adminDistrictList(i).InnerText)
AddLabel(AddressList, postalCodeList(i).InnerText)
AddLabel(AddressList, "")
AddPushpinToMap(Convert.ToDouble(latitudeList(i).InnerText), Convert.ToDouble(longitudeList(i).InnerText), Convert.ToString(i + 1))
Next i
SearchResults.Visibility = Visibility.Visible
myMap.Visibility = Visibility.Visible
myMapLabel.Visibility = Visibility.Visible
myMap.Focus() 'allows '+' and '-' to zoom the map
End If
End Sub
Complete Code Sample
The following sections contain the complete code sample.
XAML
<Window x:Class="RESTandWPFwithXML.MainWindow"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
Title="MainWindow"
Height="500" Width="800">
<Window.Resources>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<Style x:Key="BlueLabel" TargetType="Label" BasedOn="{StaticResource LabelStyle}">
<Setter Property="Foreground" Value="#FF0E6EDC"/>
</Style>
<Style x:Key="RedLabel" TargetType="Label" BasedOn="{StaticResource LabelStyle}">
<Setter Property="Foreground" Value="#FFA42E2E"/>
</Style>
<Style x:Key="AddressStyle" TargetType="Label" >
<Setter Property="Padding" Value="10px 0 0 0"/>
<Setter Property="Margin" Value="0 0 0 0" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="115"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas Name="SearchParameters" Grid.Row="0" Grid.ColumnSpan="2" Margin="0,0,36,0">
<Label Style="{StaticResource RedLabel}" >Search and Map Entities Near a Location</Label>
<Label Canvas.Left="0" Canvas.Top="24" Foreground="#FF0E6EDC" AllowDrop="True" FontWeight="Bold" Content="Search for"></Label>
<Label Style="{StaticResource LabelStyle}" AllowDrop="True" Canvas.Left="0" Canvas.Top="49"
Content="Within" FontWeight="Bold" Foreground="#FF0E6EDC" />
<ComboBox Canvas.Left="50" Name="Distance" Canvas.Top="53" Height="20" >
<ComboBoxItem IsSelected="True">1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>5</ComboBoxItem>
</ComboBox>
<TextBox Height="25" Name="SearchNearby" Width="175" Text="Insert location" Canvas.Left="138" Canvas.Top="52" />
<Label Style="{StaticResource BlueLabel}" Canvas.Left="90" Canvas.Top="49" Content="km of " Height="28" Name="label1" />
<Button Click="Search_Click" Width="59" Height="24" Grid.ColumnSpan="2" Margin="0,77,251,39" HorizontalAlignment="Right" Canvas.Left="319" Canvas.Top="-25">Search</Button>
<ComboBox Name="EntityType" Canvas.Left="73" Canvas.Top="29" Height="21" Width="117" >
<ComboBoxItem Tag="7011" IsSelected="True">Hotel</ComboBoxItem>
<ComboBoxItem Tag="5800">Restaurant</ComboBoxItem>
<ComboBoxItem Tag="7999">Tourist Attraction</ComboBoxItem>
</ComboBox>
</Canvas>
<StackPanel Grid.Row="1" Grid.Column="0">
<Label Name="ErrorMessage" Visibility="Collapsed" ></Label>
<ScrollViewer Name="SearchResults" Visibility="Collapsed" Height="300">
<StackPanel Name="AddressList" ></StackPanel>
</ScrollViewer>
</StackPanel>
<StackPanel Grid.Row="1"
Grid.Column="1" >
<m:Map Visibility="Hidden" x:Name="myMap"
CredentialsProvider="Insert_Your_Bing_Maps_Key" Height="300" Width="300" />
<Label Name="myMapLabel" Visibility="Hidden" HorizontalAlignment="Center" >Use + and - to zoom in and out</Label>
</StackPanel>
</Grid>
</Window>
C# Code-behind
using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Maps.MapControl.WPF;
using Microsoft.Maps.MapControl.WPF.Design;
using System.Xml;
using System.Net;
using System.Xml.XPath;
namespace RESTandWPFwithXML
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string BingMapsKey = "Insert_Your_Bing_Maps_Key";
public MainWindow()
{
InitializeComponent();
}
// Geocode an address and return a latitude and longitude
public XmlDocument Geocode(string addressQuery)
{
//Create REST Services geocode request using Locations API
string geocodeRequest = "http://dev.virtualearth.net/REST/v1/Locations/" + addressQuery + "?o=xml&key=" + BingMapsKey;
//Make the request and get the response
XmlDocument geocodeResponse = GetXmlResponse(geocodeRequest);
return (geocodeResponse);
}
// Submit a REST Services or Spatial Data Services request and return the response
private XmlDocument GetXmlResponse(string requestUrl)
{
System.Diagnostics.Trace.WriteLine("Request URL (XML): " + requestUrl);
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format("Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(response.GetResponseStream());
return xmlDoc;
}
}
//Search for POI near a point
private void FindandDisplayNearbyPOI(XmlDocument xmlDoc)
{
//Get location information from geocode response
//Create namespace manager
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("rest", "https://schemas.microsoft.com/search/local/ws/rest/v1");
//Get all geocode locations in the response
XmlNodeList locationElements = xmlDoc.SelectNodes("//rest:Location", nsmgr);
if (locationElements.Count == 0)
{
ErrorMessage.Visibility = Visibility.Visible;
ErrorMessage.Content = "The location you entered could not be geocoded.";
}
else
{
//Get the geocode location points that are used for display (UsageType=Display)
XmlNodeList displayGeocodePoints =
locationElements[0].SelectNodes(".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()", nsmgr);
string latitude = displayGeocodePoints[0].SelectSingleNode(".//rest:Latitude", nsmgr).InnerText;
string longitude = displayGeocodePoints[0].SelectSingleNode(".//rest:Longitude", nsmgr).InnerText;
ComboBoxItem entityTypeID = (ComboBoxItem)EntityType.SelectedItem;
ComboBoxItem distance = (ComboBoxItem)Distance.SelectedItem;
//Create the Bing Spatial Data Services request to get the user-specified POI entity type near the selected point
string findNearbyPOIRequest = "http://spatial.virtualearth.net/REST/v1/data/f22876ec257b474b82fe2ffcb8393150/NavteqNA/NavteqPOIs?spatialfilter=nearby("
+ latitude + "," + longitude + "," + distance.Content + ")"
+ "&$filter=EntityTypeID%20EQ%20'" + entityTypeID.Tag + "'&$select=EntityID,DisplayName,__Distance,Latitude,Longitude,AddressLine,Locality,AdminDistrict,PostalCode&$top=10"
+ "&key=" + BingMapsKey;
//Submit the Bing Spatial Data Services request and retrieve the response
XmlDocument nearbyPOI = GetXmlResponse(findNearbyPOIRequest);
//Center the map at the geocoded location and display the results
myMap.Center = new Location(Convert.ToDouble(latitude), Convert.ToDouble(longitude));
myMap.ZoomLevel = 12;
DisplayResults(nearbyPOI);
}
}
//Add label element to application
private void AddLabel(Panel parent, string labelString)
{
Label dname = new Label();
dname.Content = labelString;
dname.Style = (Style)FindResource("AddressStyle");
parent.Children.Add(dname);
}
//Add a pushpin with a label to the map
private void AddPushpinToMap(double latitude, double longitude, string pinLabel)
{
Location location = new Location(latitude, longitude);
Pushpin pushpin = new Pushpin();
pushpin.Content = pinLabel;
pushpin.Location = location;
myMap.Children.Add(pushpin);
}
//Show the POI address information and insert pushpins on the map
private void DisplayResults(XmlDocument nearbyPOI)
{
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nearbyPOI.NameTable);
nsmgr.AddNamespace("d", "https://schemas.microsoft.com/ado/2007/08/dataservices");
nsmgr.AddNamespace("m", "https://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
nsmgr.AddNamespace("a", "http://www.w3.org/2005/Atom");
//Get the the entityID for each POI entity in the response
XmlNodeList displayNameList = nearbyPOI.SelectNodes("//d:DisplayName", nsmgr);
//Provide entity information and put a pushpin on the map.
if (displayNameList.Count == 0)
{
ErrorMessage.Content = "No results were found for this location.";
ErrorMessage.Visibility = Visibility.Visible;
}
else
{
XmlNodeList addressLineList = nearbyPOI.SelectNodes("//d:AddressLine", nsmgr);
XmlNodeList localityList = nearbyPOI.SelectNodes("//d:Locality", nsmgr);
XmlNodeList adminDistrictList = nearbyPOI.SelectNodes("//d:AdminDistrict", nsmgr);
XmlNodeList postalCodeList = nearbyPOI.SelectNodes("//d:PostalCode", nsmgr);
XmlNodeList latitudeList = nearbyPOI.SelectNodes("//d:Latitude", nsmgr);
XmlNodeList longitudeList = nearbyPOI.SelectNodes("//d:Longitude", nsmgr);
for (int i = 0; i < displayNameList.Count; i++)
{
AddLabel(AddressList, "[" + Convert.ToString(i + 1) + "] " + displayNameList[i].InnerText);
AddLabel(AddressList, addressLineList[i].InnerText);
AddLabel(AddressList, localityList[i].InnerText + ", " + adminDistrictList[i].InnerText);
AddLabel(AddressList, postalCodeList[i].InnerText);
AddLabel(AddressList, "");
AddPushpinToMap(Convert.ToDouble(latitudeList[i].InnerText), Convert.ToDouble(longitudeList[i].InnerText), Convert.ToString(i + 1));
}
SearchResults.Visibility = Visibility.Visible;
myMap.Visibility = Visibility.Visible;
myMapLabel.Visibility = Visibility.Visible;
myMap.Focus(); //allows '+' and '-' to zoom the map
}
}
//Search for POI elements when the Search button is clicked
private void Search_Click(object sender, RoutedEventArgs e)
{
//Clear prior search
myMap.Visibility = Visibility.Hidden;
myMapLabel.Visibility = Visibility.Collapsed;
myMap.Children.Clear();
SearchResults.Visibility = Visibility.Collapsed;
AddressList.Children.Clear();
ErrorMessage.Visibility = Visibility.Collapsed;
//Get latitude and longitude coordinates for specified location
XmlDocument searchResponse = Geocode(SearchNearby.Text);
//Find and display points of interest near the specified location
FindandDisplayNearbyPOI(searchResponse);
}
}
}
Visual Basic Code-behind
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Maps.MapControl.WPF
Imports Microsoft.Maps.MapControl.WPF.Design
Imports System.Xml
Imports System.Net
Imports System.Xml.XPath
Namespace RESTandWPFwithXML
''' <summary>
''' Interaction logic for MainWindow.xaml
''' </summary>
Partial Public Class MainWindow
Inherits Window
Private BingMapsKey As String = "Insert_Your_Bing_Maps_Key"
Public Sub New()
InitializeComponent()
End Sub
' Geocode an address and return a latitude and longitude
Public Function Geocode(ByVal addressQuery As String) As XmlDocument
'Create REST Services geocode request using Locations API
Dim geocodeRequest As String = "http://dev.virtualearth.net/REST/v1/Locations/" & addressQuery & "?o=xml&key=" & BingMapsKey
'Make the request and get the response
Dim geocodeResponse As XmlDocument = GetXmlResponse(geocodeRequest)
Return (geocodeResponse)
End Function
' Submit a REST Services or Spatial Data Services request and return the response
Private Function GetXmlResponse(ByVal requestUrl As String) As XmlDocument
System.Diagnostics.Trace.WriteLine("Request URL (XML): " & requestUrl)
Dim request As HttpWebRequest = TryCast(WebRequest.Create(requestUrl), HttpWebRequest)
Using response As HttpWebResponse = TryCast(request.GetResponse(), HttpWebResponse)
If response.StatusCode <> HttpStatusCode.OK Then
Throw New Exception(String.Format("Server error (HTTP {0}: {1}).", response.StatusCode, response.StatusDescription))
End If
Dim xmlDoc As New XmlDocument()
xmlDoc.Load(response.GetResponseStream())
Return xmlDoc
End Using
End Function
'Search for POI near a point
Private Sub FindandDisplayNearbyPOI(ByVal xmlDoc As XmlDocument)
'Get location information from geocode response
'Create namespace manager
Dim nsmgr As New XmlNamespaceManager(xmlDoc.NameTable)
nsmgr.AddNamespace("rest", "https://schemas.microsoft.com/search/local/ws/rest/v1")
'Get all locations in the response and then extract the coordinates for the top location
Dim locationElements As XmlNodeList = xmlDoc.SelectNodes("//rest:Location", nsmgr)
If locationElements.Count = 0 Then
ErrorMessage.Visibility = Visibility.Visible
ErrorMessage.Content = "The location you entered could not be geocoded."
Else
'Get the geocode points that are used for display (UsageType=Display)
Dim displayGeocodePoints As XmlNodeList = locationElements(0).SelectNodes(".//rest:GeocodePoint/rest:UsageType[.='Display']/parent::node()", nsmgr)
Dim latitude As String = displayGeocodePoints(0).SelectSingleNode(".//rest:Latitude", nsmgr).InnerText
Dim longitude As String = displayGeocodePoints(0).SelectSingleNode(".//rest:Longitude", nsmgr).InnerText
Dim entityTypeID As ComboBoxItem = CType(EntityType.SelectedItem, ComboBoxItem)
Dim distance As ComboBoxItem = CType(Distance.SelectedItem, ComboBoxItem)
'Create the Bing Spatial Data Services request to get nearby POI
Dim findNearbyPOIRequest As String = "http://spatial.virtualearth.net/REST/v1/data/f22876ec257b474b82fe2ffcb8393150/NavteqNA/NavteqPOIs?spatialfilter=nearby(" & latitude & "," & longitude & "," & distance.Content & ")" & "&$filter=EntityTypeID%20EQ%20'" & entityTypeID.Tag & "'&$select=EntityID,DisplayName,__Distance,Latitude,Longitude,AddressLine,Locality,AdminDistrict,PostalCode&$top=10" & "&key=" & BingMapsKey
'Submit the Bing Spatial Data Services request and retrieve the response
Dim nearbyPOI As XmlDocument = GetXmlResponse(findNearbyPOIRequest)
'Center the map at the geocoded location and display the results
myMap.Center = New Location(Convert.ToDouble(latitude), Convert.ToDouble(longitude))
myMap.ZoomLevel = 12
DisplayResults(nearbyPOI)
End If
End Sub
'Add label element to application
Private Sub AddLabel(ByVal parent As Panel, ByVal labelString As String)
Dim dname As New Label()
dname.Content = labelString
dname.Style = CType(FindResource("AddressStyle"), Style)
parent.Children.Add(dname)
End Sub
'Add a pushpin with a label to the map
Private Sub AddPushpinToMap(ByVal latitude As Double, ByVal longitude As Double, ByVal pinLabel As String)
Dim location As New Location(latitude, longitude)
Dim pushpin As New Pushpin()
pushpin.Content = pinLabel
pushpin.Location = location
myMap.Children.Add(pushpin)
End Sub
'Show the POI address information and insert pushpins on the map
Private Sub DisplayResults(ByVal nearbyPOI As XmlDocument)
Dim nsmgr As New XmlNamespaceManager(nearbyPOI.NameTable)
nsmgr.AddNamespace("d", "https://schemas.microsoft.com/ado/2007/08/dataservices")
nsmgr.AddNamespace("m", "https://schemas.microsoft.com/ado/2007/08/dataservices/metadata")
nsmgr.AddNamespace("a", "http://www.w3.org/2005/Atom")
'Get the the entityID for each POI entity in the response
Dim displayNameList As XmlNodeList = nearbyPOI.SelectNodes("//d:DisplayName", nsmgr)
'Provide entity information and put a pushpin on the map.
If displayNameList.Count = 0 Then
ErrorMessage.Content = "No results were found for this location."
ErrorMessage.Visibility = Visibility.Visible
Else
Dim addressLineList As XmlNodeList = nearbyPOI.SelectNodes("//d:AddressLine", nsmgr)
Dim localityList As XmlNodeList = nearbyPOI.SelectNodes("//d:Locality", nsmgr)
Dim adminDistrictList As XmlNodeList = nearbyPOI.SelectNodes("//d:AdminDistrict", nsmgr)
Dim postalCodeList As XmlNodeList = nearbyPOI.SelectNodes("//d:PostalCode", nsmgr)
Dim latitudeList As XmlNodeList = nearbyPOI.SelectNodes("//d:Latitude", nsmgr)
Dim longitudeList As XmlNodeList = nearbyPOI.SelectNodes("//d:Longitude", nsmgr)
For i As Integer = 0 To displayNameList.Count - 1
AddLabel(AddressList, "[" & Convert.ToString(i + 1) & "] " & displayNameList(i).InnerText)
AddLabel(AddressList, addressLineList(i).InnerText)
AddLabel(AddressList, localityList(i).InnerText & ", " & adminDistrictList(i).InnerText)
AddLabel(AddressList, postalCodeList(i).InnerText)
AddLabel(AddressList, "")
AddPushpinToMap(Convert.ToDouble(latitudeList(i).InnerText), Convert.ToDouble(longitudeList(i).InnerText), Convert.ToString(i + 1))
Next i
SearchResults.Visibility = Visibility.Visible
myMap.Visibility = Visibility.Visible
myMapLabel.Visibility = Visibility.Visible
myMap.Focus() 'allows '+' and '-' to zoom the map
End If
End Sub
'Search for POI elements when the Search button is clicked
Private Sub Search_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
'Clear prior search
myMap.Visibility = Visibility.Hidden
myMapLabel.Visibility = Visibility.Collapsed
myMap.Children.Clear()
SearchResults.Visibility = Visibility.Collapsed
AddressList.Children.Clear()
ErrorMessage.Visibility = Visibility.Collapsed
'Get latitude and longitude coordinates for specified location
Dim searchResponse As XmlDocument = Geocode(SearchNearby.Text)
'Find and display points of interest near the specified location
FindandDisplayNearbyPOI(searchResponse)
End Sub
End Class