XAML-Map-Control/MapControl/Shared/BingMapsTileLayer.cs

118 lines
3.8 KiB
C#
Raw Normal View History

2017-08-04 21:38:58 +02:00
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
2024-02-03 21:01:53 +01:00
// Copyright © 2024 Clemens Fischer
2017-08-04 21:38:58 +02:00
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
2019-11-07 22:34:25 +01:00
using System.Xml.Linq;
2024-05-22 11:25:32 +02:00
#if WPF
using System.Windows;
2021-11-17 23:17:11 +01:00
#elif UWP
2017-08-04 21:38:58 +02:00
using Windows.UI.Xaml;
2024-05-22 11:25:32 +02:00
#elif WINUI
using Microsoft.UI.Xaml;
2017-08-04 21:38:58 +02:00
#endif
namespace MapControl
{
/// <summary>
/// Displays Bing Maps tiles. The static ApiKey property must be set to a Bing Maps API Key.
/// Tile image URLs and min/max zoom levels are retrieved from the Imagery Metadata Service
/// (see http://msdn.microsoft.com/en-us/library/ff701716.aspx).
/// </summary>
public class BingMapsTileLayer : MapTileLayer
{
public enum MapMode
{
Road, Aerial, AerialWithLabels
}
public BingMapsTileLayer()
{
MinZoomLevel = 1;
MaxZoomLevel = 21;
Loaded += OnLoaded;
}
public static string ApiKey { get; set; }
public MapMode Mode { get; set; }
public string Culture { get; set; }
2017-10-07 17:43:28 +02:00
public Uri LogoImageUri { get; private set; }
2017-08-04 21:38:58 +02:00
2019-11-07 22:34:25 +01:00
private async void OnLoaded(object sender, RoutedEventArgs args)
2017-08-04 21:38:58 +02:00
{
Loaded -= OnLoaded;
2020-04-14 22:41:34 +02:00
if (!string.IsNullOrEmpty(ApiKey))
2017-08-04 21:38:58 +02:00
{
2022-08-18 22:30:22 +02:00
var metadataUri = $"https://dev.virtualearth.net/REST/V1/Imagery/Metadata/{Mode}?output=xml&key={ApiKey}";
2017-08-04 21:38:58 +02:00
2020-04-14 22:41:34 +02:00
try
2020-03-20 18:12:56 +01:00
{
2020-04-14 22:41:34 +02:00
using (var stream = await ImageLoader.HttpClient.GetStreamAsync(metadataUri))
{
ReadImageryMetadata(XDocument.Load(stream).Root);
}
}
catch (Exception ex)
{
2024-08-31 16:39:49 +02:00
Debug.WriteLine($"{nameof(BingMapsTileLayer)}: {metadataUri}: {ex.Message}");
2020-03-20 18:12:56 +01:00
}
2017-08-04 21:38:58 +02:00
}
2020-04-14 22:41:34 +02:00
else
2017-08-04 21:38:58 +02:00
{
2024-08-31 16:39:49 +02:00
Debug.WriteLine($"{nameof(BingMapsTileLayer)} requires a Bing Maps API Key");
2017-08-04 21:38:58 +02:00
}
}
2020-03-20 18:12:56 +01:00
private void ReadImageryMetadata(XElement metadataResponse)
2017-08-04 21:38:58 +02:00
{
var ns = metadataResponse.Name.Namespace;
var metadata = metadataResponse.Descendants(ns + "ImageryMetadata").FirstOrDefault();
2017-08-04 21:38:58 +02:00
if (metadata != null)
{
var imageUrl = metadata.Element(ns + "ImageUrl")?.Value;
var subdomains = metadata.Element(ns + "ImageUrlSubdomains")?.Elements(ns + "string").Select(e => e.Value).ToArray();
2017-08-04 21:38:58 +02:00
if (!string.IsNullOrEmpty(imageUrl) && subdomains != null && subdomains.Length > 0)
2017-08-04 21:38:58 +02:00
{
var zoomMin = metadata.Element(ns + "ZoomMin")?.Value;
var zoomMax = metadata.Element(ns + "ZoomMax")?.Value;
2020-04-16 19:24:38 +02:00
if (zoomMin != null && int.TryParse(zoomMin, out int zoomLevel) && MinZoomLevel < zoomLevel)
{
MinZoomLevel = zoomLevel;
}
if (zoomMax != null && int.TryParse(zoomMax, out zoomLevel) && MaxZoomLevel > zoomLevel)
{
MaxZoomLevel = zoomLevel;
}
if (string.IsNullOrEmpty(Culture))
{
Culture = CultureInfo.CurrentUICulture.Name;
}
2020-10-23 23:35:48 +02:00
TileSource = new BingMapsTileSource
{
UriTemplate = imageUrl.Replace("{culture}", Culture),
2020-10-23 23:35:48 +02:00
Subdomains = subdomains
};
2017-08-04 21:38:58 +02:00
}
}
2017-08-04 21:38:58 +02:00
var logoUri = metadataResponse.Element(ns + "BrandLogoUri");
2017-08-04 21:38:58 +02:00
if (logoUri != null)
{
LogoImageUri = new Uri(logoUri.Value);
2017-08-04 21:38:58 +02:00
}
}
}
}