
This topic provides information on how to display geographic imagery from Bing Maps in the background content of the XamGeographicMap™ control.
The following table lists the topics required as a prerequisite to understanding this topic.
This topic contains the following sections:
The Bing Maps is a licensed geographic imagery mapping service created by the Microsoft® company. This geographic imagery service can be access directly on http://www.bing.com/maps web site. The control displays geographic imagery from the Bing Maps in the map background content using the BingMapsMapImagery class. However, the control by the default displays geographic imagery from the Open Street Maps in the map background content. Therefore, you must configure the control to display geographic imagery from the Bing Maps.
The following images are previews of the control in supported map styles of geographic imagery from the Bing Maps service.
To complete the following procedure, you need to fulfill the following requirements:
The following code provides implementation of the Bing Maps Connector class.
In Visual Basic:
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Net ' HttpWebRequest
Imports System.Runtime.Serialization ' DataContract, DataMember
Imports System.Runtime.Serialization.Json ' DataContractJsonSerializer
Imports System.Windows
Namespace Infragistics.Samples.Services
''' <summary>
''' <para> Represents a connector class that sets up BingMaps REST imagery service </para>
''' <para> and provides imagery tiles via Http web requests.</para>
''' <remarks>Bing Maps REST Services: http://msdn.microsoft.com/en-us/library/ff701713.aspx </remarks>
''' </summary>
Public Class BingMapsConnector
Inherits DependencyObject
Implements INotifyPropertyChanged
Public Sub New()
Me.IsInitialized = False
End Sub
#Region "Events"
Public Event ImageryInitialized As EventHandler
Public Event PropertyChanged As PropertyChangedEventHandler
#End Region
#Region "Properties"
''' <summary>
''' Gets or sets an API key required by the Bing Maps imagery service.
''' <remarks>This key must be obtained from the http://www.bingmapsportal.com website. </remarks>
''' </summary>
Public Property ApiKey() As String
Get
Return DirectCast(GetValue(ApiKeyProperty), String)
End Get
Set
SetValue(ApiKeyProperty, value)
End Set
End Property
Public Const ApiKeyPropertyName As String = "ApiKey"
Public Shared ReadOnly ApiKeyProperty As DependencyProperty = DependencyProperty.Register(ApiKeyPropertyName, GetType(String), GetType(BingMapsConnector), New PropertyMetadata(String.Empty, Function(o, e) TryCast(o, BingMapsConnector).OnApiKeyChanged(DirectCast(e.OldValue, String), DirectCast(e.NewValue, String))))
Private Sub OnApiKeyChanged(oldValue As String, newValue As String)
Me.Validate()
End Sub
Public Const ImageryStylePropertyName As String = "ImageryStyle"
''' <summary>
''' <para> Gets or sets a map style of the Bing Maps imagery tiles. </para>
''' <para> For example: Aerial, AerialWithLabels, or Road map style. </para>
''' </summary>
Public Property ImageryStyle() As BingMapsImageryStyle
Get
Return CType(GetValue(ImageryStyleProperty), BingMapsImageryStyle)
End Get
Set
SetValue(ImageryStyleProperty, value)
End Set
End Property
Public Shared ReadOnly ImageryStyleProperty As DependencyProperty = DependencyProperty.Register(ImageryStylePropertyName, GetType(BingMapsImageryStyle), GetType(BingMapsConnector), New PropertyMetadata(BingMapsImageryStyle.AerialWithLabels, Function(o, e) TryCast(o, BingMapsConnector).OnImageryStylePropertyChanged(CType(e.OldValue, BingMapsImageryStyle), CType(e.NewValue, BingMapsImageryStyle))))
Private Sub OnImageryStylePropertyChanged(oldValue As BingMapsImageryStyle, newValue As BingMapsImageryStyle)
Me.Validate()
End Sub
Private _tilePath As String
''' <summary>
''' Gets an imagery tile path for the Bing Maps service.
''' </summary>
Public Property TilePath() As String
Get
Return _tilePath
End Get
Private Set
_tilePath = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("TilePath"))
End Set
End Property
Private _subDomains As ObservableCollection(Of String)
''' <summary>
''' Gets a collection of image URI sub-domains for the Bing Maps service.
''' </summary>
Public Property SubDomains() As ObservableCollection(Of String)
Get
Return _subDomains
End Get
Private Set
_subDomains = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("SubDomains"))
End Set
End Property
''' <summary>
''' Gets a status whether the Bing Maps service is initialized.
''' </summary>
Public Property IsInitialized() As Boolean
Get
Return _IsInitialized
End Get
Private Set
_IsInitialized = Value
End Set
End Property
Private _IsInitialized As Boolean
''' <summary>
''' Gets or sets whether the Bing Maps service should be auto-initialized upon valid property values.
''' </summary>
Public Property IsAutoInitialized() As Boolean
Get
Return CBool(GetValue(IsAutoInitializedProperty))
End Get
Set
SetValue(IsAutoInitializedProperty, value)
End Set
End Property
Public Const IsAutoInitializedPropertyName As String = "IsAutoInitialized"
Public Shared ReadOnly IsAutoInitializedProperty As DependencyProperty = DependencyProperty.Register(IsAutoInitializedPropertyName, GetType(Boolean), GetType(BingMapsConnector), New PropertyMetadata(False, Function(o, e) TryCast(o, BingMapsConnector).OnAutoInitializedChanged(CBool(e.OldValue), CBool(e.NewValue))))
Private Sub OnAutoInitializedChanged(oldValue As Boolean, newValue As Boolean)
Me.Validate()
End Sub
#End Region
#Region "Methods"
Private Sub Validate()
Me.IsInitialized = False
If Not IsValidApiKey() Then
Return
End If
If Me.IsAutoInitialized Then
Initialize()
End If
End Sub
Private Function IsValidApiKey() As Boolean
If [String].IsNullOrEmpty(Me.ApiKey) OrElse Me.ApiKey.Length < 20 Then
Return False
End If
Return True
End Function
Public Sub Initialize()
If Not IsValidApiKey() Then
Me.IsInitialized = False
System.Diagnostics.Debug.WriteLine("Detected Invalid BingMaps API key: " & Me.ApiKey)
Return
End If
Me.IsInitialized = True
' for more info on setting up web requests to BingMaps REST imagery service
' refer to: http://msdn.microsoft.com/en-us/library/ff701716.aspx
Dim bingUrl = "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/"
Dim imagerySet = Me.ImageryStyle
bingUrl += imagerySet
Dim parms = "key=" & Me.ApiKey & "&include=ImageryProviders"
Dim url = bingUrl & "?" & parms
Dim req = HttpWebRequest.Create(url)
req.BeginGetResponse(AddressOf GetResponseCompleted, req)
End Sub
#End Region
#Region "Event Handlers"
Private Sub GetResponseCompleted(res As IAsyncResult)
Dim req = DirectCast(res.AsyncState, HttpWebRequest)
Dim response = req.EndGetResponse(res)
' alternatively, parsing of BingResponse can be performed using LINQ to XML
' instead of using JSON deserializer
Dim json = New DataContractJsonSerializer(GetType(BingResponse))
Dim resp = DirectCast(json.ReadObject(response.GetResponseStream()), BingResponse)
If resp.ResourceSets Is Nothing OrElse resp.ResourceSets.Count < 1 OrElse resp.ResourceSets(0).Resources Is Nothing OrElse resp.ResourceSets(0).Resources.Count < 1 Then
Return
End If
Dim imageUrl = resp.ResourceSets(0).Resources(0).ImageUrl
Dim subDomains__1 = resp.ResourceSets(0).Resources(0).ImageUrlSubdomains
If imageUrl Is Nothing OrElse subDomains__1 Is Nothing Then
Return
End If
TilePath = imageUrl
SubDomains = New ObservableCollection(Of String)(subDomains__1)
RaiseEvent ImageryInitialized(Me, New EventArgs())
End Sub
#End Region
End Class
''' <summary>
''' Determines map style for the Bing Maps imagery.
''' </summary>
Public Enum BingMapsImageryStyle
''' <summary>
''' Specifies the Aerial map style without road or labels overlay.
''' </summary>
Aerial
''' <summary>
''' Specifies the Aerial map style with road and labels overlay.
''' </summary>
AerialWithLabels
''' <summary>
''' Specifies the Roads map style without aerial overlay.
''' </summary>
Road
#Region "Not supported Bing Maps styles by the XamGeographicMap control"
'''// <summary>
'''// Specifies the Bird’s eye (oblique-angle) map style
'''// </summary>
'Birdseye,
'''// <summary>
'''// Specifies the Bird’s eye map style with road and labels overlay.
'''// </summary>
'BirdseyeWithLabels,
#End Region
End Enum
<DataContract> _
Public Class BingResponse
Public Sub New()
ResourceSets = New List(Of BingResourceSet)()
End Sub
<DataMember(Name := "resourceSets")> _
Public Property ResourceSets() As List(Of BingResourceSet)
Get
Return _ResourceSets
End Get
Set
_ResourceSets = Value
End Set
End Property
Private _ResourceSets As List(Of BingResourceSet)
End Class
<DataContract> _
Public Class BingResourceSet
Public Sub New()
Resources = New List(Of ImageryMetadata)()
End Sub
<DataMember(Name := "resources")> _
Public Property Resources() As List(Of ImageryMetadata)
Get
Return _Resources
End Get
Set
_Resources = Value
End Set
End Property
Private _Resources As List(Of ImageryMetadata)
End Class
<DataContract([Namespace] := "http://schemas.microsoft.com/search/local/ws/rest/v1")> _
Public Class ImageryMetadata
Public Sub New()
ImageUrlSubdomains = New List(Of String)()
End Sub
<DataMember(Name := "imageUrl")> _
Public Property ImageUrl() As String
Get
Return _ImageUrl
End Get
Set
_ImageUrl = Value
End Set
End Property
Private _ImageUrl As String
<DataMember(Name := "imageUrlSubdomains")> _
Public Property ImageUrlSubdomains() As List(Of String)
Get
Return _ImageUrlSubdomains
End Get
Set
_ImageUrlSubdomains = Value
End Set
End Property
Private _ImageUrlSubdomains As List(Of String)
End Class
End Namespace
In C#:
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Net; // HttpWebRequest
using System.Runtime.Serialization; // DataContract, DataMember
using System.Runtime.Serialization.Json; // DataContractJsonSerializer
using System.Windows;
namespace Infragistics.Samples.Services
{
/// <summary>
/// <para> Represents a connector class that sets up BingMaps REST imagery service </para>
/// <para> and provides imagery tiles via Http web requests.</para>
/// <remarks>Bing Maps REST Services: http://msdn.microsoft.com/en-us/library/ff701713.aspx </remarks>
/// </summary>
public class BingMapsConnector : DependencyObject, INotifyPropertyChanged
{
public BingMapsConnector()
{
this.IsInitialized = false;
}
#region Events
public event EventHandler ImageryInitialized;
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Properties
/// <summary>
/// Gets or sets an API key required by the Bing Maps imagery service.
/// <remarks>This key must be obtained from the http://www.bingmapsportal.com website. </remarks>
/// </summary>
public string ApiKey
{
get { return (string)GetValue(ApiKeyProperty); }
set { SetValue(ApiKeyProperty, value); }
}
public const string ApiKeyPropertyName = "ApiKey";
public static readonly DependencyProperty ApiKeyProperty =
DependencyProperty.Register(ApiKeyPropertyName, typeof(string), typeof(BingMapsConnector),
new PropertyMetadata(string.Empty, (o, e) => (o as BingMapsConnector).OnApiKeyChanged((string)e.OldValue, (string)e.NewValue)));
private void OnApiKeyChanged(string oldValue, string newValue)
{
this.Validate();
}
public const string ImageryStylePropertyName = "ImageryStyle";
/// <summary>
/// <para> Gets or sets a map style of the Bing Maps imagery tiles. </para>
/// <para> For example: Aerial, AerialWithLabels, or Road map style. </para>
/// </summary>
public BingMapsImageryStyle ImageryStyle
{
get { return (BingMapsImageryStyle)GetValue(ImageryStyleProperty); }
set { SetValue(ImageryStyleProperty, value); }
}
public static readonly DependencyProperty ImageryStyleProperty =
DependencyProperty.Register(ImageryStylePropertyName, typeof(BingMapsImageryStyle), typeof(BingMapsConnector),
new PropertyMetadata(BingMapsImageryStyle.AerialWithLabels, (o, e) =>
(o as BingMapsConnector).OnImageryStylePropertyChanged((BingMapsImageryStyle)e.OldValue, (BingMapsImageryStyle)e.NewValue)));
private void OnImageryStylePropertyChanged(BingMapsImageryStyle oldValue, BingMapsImageryStyle newValue)
{
this.Validate();
}
private string _tilePath;
/// <summary>
/// Gets an imagery tile path for the Bing Maps service.
/// </summary>
public string TilePath
{
get { return _tilePath; }
private set
{
_tilePath = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("TilePath"));
}
}
}
private ObservableCollection<string> _subDomains;
/// <summary>
/// Gets a collection of image URI sub-domains for the Bing Maps service.
/// </summary>
public ObservableCollection<string> SubDomains
{
get
{
return _subDomains;
}
private set
{
_subDomains = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SubDomains"));
}
}
}
/// <summary>
/// Gets a status whether the Bing Maps service is initialized.
/// </summary>
public bool IsInitialized { get; private set; }
/// <summary>
/// Gets or sets whether the Bing Maps service should be auto-initialized upon valid property values.
/// </summary>
public bool IsAutoInitialized
{
get { return (bool)GetValue(IsAutoInitializedProperty); }
set { SetValue(IsAutoInitializedProperty, value); }
}
public const string IsAutoInitializedPropertyName = "IsAutoInitialized";
public static readonly DependencyProperty IsAutoInitializedProperty =
DependencyProperty.Register(IsAutoInitializedPropertyName, typeof(bool), typeof(BingMapsConnector),
new PropertyMetadata(false, (o, e) => (o as BingMapsConnector).OnAutoInitializedChanged((bool)e.OldValue, (bool)e.NewValue)));
private void OnAutoInitializedChanged(bool oldValue, bool newValue)
{
this.Validate();
}
#endregion
#region Methods
private void Validate()
{
this.IsInitialized = false;
if (!IsValidApiKey())
{
return;
}
if (this.IsAutoInitialized)
{
Initialize();
}
}
private bool IsValidApiKey()
{
if (String.IsNullOrEmpty(this.ApiKey) || this.ApiKey.Length < 20)
{
return false;
}
return true;
}
public void Initialize()
{
if (!IsValidApiKey())
{
this.IsInitialized = false;
System.Diagnostics.Debug.WriteLine("Detected Invalid BingMaps API key: " + this.ApiKey);
return;
}
this.IsInitialized = true;
// for more info on setting up web requests to BingMaps REST imagery service
// refer to: http://msdn.microsoft.com/en-us/library/ff701716.aspx
var bingUrl = "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/";
var imagerySet = this.ImageryStyle;
bingUrl += imagerySet;
var parms = "key=" + this.ApiKey + "&include=ImageryProviders";
var url = bingUrl + "?" + parms;
var req = HttpWebRequest.Create(url);
req.BeginGetResponse(GetResponseCompleted, req);
}
#endregion
#region Event Handlers
private void GetResponseCompleted(IAsyncResult res)
{
var req = (HttpWebRequest)res.AsyncState;
var response = req.EndGetResponse(res);
// alternatively, parsing of BingResponse can be performed using LINQ to XML
// instead of using JSON deserializer
var json = new DataContractJsonSerializer(typeof(BingResponse));
var resp = (BingResponse)json.ReadObject(response.GetResponseStream());
if (resp.ResourceSets == null ||
resp.ResourceSets.Count < 1 ||
resp.ResourceSets[0].Resources == null ||
resp.ResourceSets[0].Resources.Count < 1)
{
return;
}
var imageUrl = resp.ResourceSets[0].Resources[0].ImageUrl;
var subDomains = resp.ResourceSets[0].Resources[0].ImageUrlSubdomains;
if (imageUrl == null || subDomains == null)
{
return;
}
TilePath = imageUrl;
SubDomains = new ObservableCollection<string>(subDomains);
if (ImageryInitialized != null)
{
ImageryInitialized(this, new EventArgs());
}
}
#endregion
}
/// <summary>
/// Determines map style for the Bing Maps imagery.
/// </summary>
public enum BingMapsImageryStyle
{
/// <summary>
/// Specifies the Aerial map style without road or labels overlay.
/// </summary>
Aerial,
/// <summary>
/// Specifies the Aerial map style with road and labels overlay.
/// </summary>
AerialWithLabels,
/// <summary>
/// Specifies the Roads map style without aerial overlay.
/// </summary>
Road,
#region Not supported Bing Maps styles by the XamGeographicMap control
///// <summary>
///// Specifies the Bird’s eye (oblique-angle) map style
///// </summary>
//Birdseye,
///// <summary>
///// Specifies the Bird’s eye map style with road and labels overlay.
///// </summary>
//BirdseyeWithLabels,
#endregion
}
[DataContract]
public class BingResponse
{
public BingResponse()
{
ResourceSets = new List<BingResourceSet>();
}
[DataMember(Name = "resourceSets")]
public List<BingResourceSet> ResourceSets { get; set; }
}
[DataContract]
public class BingResourceSet
{
public BingResourceSet()
{
Resources = new List<ImageryMetadata>();
}
[DataMember(Name = "resources")]
public List<ImageryMetadata> Resources { get; set; }
}
[DataContract(Namespace = "http://schemas.microsoft.com/search/local/ws/rest/v1")]
public class ImageryMetadata
{
public ImageryMetadata()
{
ImageUrlSubdomains = new List<string>();
}
[DataMember(Name = "imageUrl")]
public string ImageUrl { get; set; }
[DataMember(Name = "imageUrlSubdomains")]
public List<string> ImageUrlSubdomains { get; set; }
}
}
The following table summarizes important members of the Bing Maps Connector class:
The following procedure demonstrates how to display geographic imagery from Bing Maps in the background content of the XamGeographicMap control.
Add the BingMapsConnector object with your own Bing Maps key and create an event handler for the ImageryInitialized event.
In Visual Basic:
Dim connector As New BingMapsConnector()
connector.ApiKey = "BING_MAPS_API_KEY"
connector.ImageryStyle = BingMapsImageryStyle.Road
connector.ImageryInitialized += OnImageryInitialized
connector.IsAutoInitialized = True
In C#:
BingMapsConnector connector = new BingMapsConnector();
connector.ApiKey = "BING_MAPS_API_KEY";
connector.ImageryStyle = BingMapsImageryStyle.Road;
connector.ImageryInitialized += OnImageryInitialized;
connector.IsAutoInitialized = true;
Implement an event handler for the ImageryInitialized event in order to invoke a method for updating the XamGeographicMap control with geographic imagery from Bing Maps service.
In Visual Basic:
Public Sub OnImageryInitialized(sender As Object, e As EventArgs)
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, DirectCast(Function() UpdateBingMaps(sender), Action))
End Sub
In C#:
public void OnImageryInitialized(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background,
(Action)(() => UpdateBingMaps(sender)));
}
Implement a method for updating the XamGeographicMap control with geographic imagery from Bing Maps service using the BingMapsMapImagery class.
In Visual Basic:
Private Sub UpdateBingMaps(sender As Object)
Dim connector = DirectCast(sender, Infragistics.Samples.Services.BingMapsConnector)
Me.GeoMap.BackgroundContent = New BingMapsMapImagery() With {
.TilePath = connector.TilePath, .SubDomains = connector.SubDomains }
End Sub
In C#:
private void UpdateBingMaps(object sender)
{
var connector = (Infragistics.Samples.Services.BingMapsConnector)sender;
this.GeoMap.BackgroundContent =
new BingMapsMapImagery()
{
TilePath = connector.TilePath,
SubDomains = connector.SubDomains
};
}
Build and run your project to verify the result. If you have implemented the steps correctly, the displayed should look like the one in the Previews section above.
The following topics provide additional information related to this topic.