mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2026-04-05 14:37:01 +00:00
Version 2.7.0.
- WPF TileImageLoader reverted to caching byte arrays instead of BitmapFrames. - Uses FileDb version 6.1.
This commit is contained in:
parent
bc30e1d9ca
commit
5adcd6568e
32 changed files with 336 additions and 300 deletions
|
|
@ -18,6 +18,9 @@ using System.Windows.Media.Imaging;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays Bing Maps tiles. The static ApiKey property must be set to a Bing Maps API Key.
|
||||
/// </summary>
|
||||
public class BingMapsTileLayer : TileLayer
|
||||
{
|
||||
public enum MapMode
|
||||
|
|
@ -26,6 +29,12 @@ namespace MapControl
|
|||
}
|
||||
|
||||
public BingMapsTileLayer()
|
||||
: this(new TileImageLoader())
|
||||
{
|
||||
}
|
||||
|
||||
public BingMapsTileLayer(ITileImageLoader tileImageLoader)
|
||||
: base(tileImageLoader)
|
||||
{
|
||||
MinZoomLevel = 1;
|
||||
MaxZoomLevel = 21;
|
||||
|
|
@ -43,7 +52,7 @@ namespace MapControl
|
|||
|
||||
if (string.IsNullOrEmpty(ApiKey))
|
||||
{
|
||||
throw new InvalidOperationException("A Bing Maps API Key must be assigned to the ApiKey property.");
|
||||
throw new InvalidOperationException("BingMapsTileLayer requires a Bing Maps API Key.");
|
||||
}
|
||||
|
||||
var uri = string.Format("http://dev.virtualearth.net/REST/V1/Imagery/Metadata/{0}?output=xml&key={1}", Mode, ApiKey);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace MapControl
|
|||
{
|
||||
internal class BingMapsTileSource : TileSource
|
||||
{
|
||||
private string[] subdomains;
|
||||
private readonly string[] subdomains;
|
||||
|
||||
public BingMapsTileSource(string uriFormat, string[] subdomains)
|
||||
: base(uriFormat)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Windows.Input;
|
|||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Default input event handling.
|
||||
/// MapBase with default input event handling.
|
||||
/// </summary>
|
||||
public class Map : MapBase
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Windows.Input;
|
|||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Default input event handling.
|
||||
/// MapBase with default input event handling.
|
||||
/// </summary>
|
||||
public class Map : MapBase
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using Windows.UI.Xaml.Input;
|
|||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Default input event handling.
|
||||
/// MapBase with default input event handling.
|
||||
/// </summary>
|
||||
public class Map : MapBase
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using System.Windows.Media.Animation;
|
|||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// The map control. Renders map content provided by the TileLayer or TileLayers property.
|
||||
/// The map control. Displays map content provided by the TileLayer or TileLayers property.
|
||||
/// The visible map area is defined by the Center and ZoomLevel properties.
|
||||
/// The map can be rotated by an angle that is given by the Heading property.
|
||||
/// MapBase can contain map overlay child elements like other MapPanels or MapItemsControls.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ using System.Windows;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2015 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("2.6.0")]
|
||||
[assembly: AssemblyFileVersion("2.6.0")]
|
||||
[assembly: AssemblyVersion("2.7.0")]
|
||||
[assembly: AssemblyFileVersion("2.7.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.Caching;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
|
|
@ -197,7 +198,7 @@ namespace MapControl
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Loading tile image failed: {0}", (object)ex.Message);
|
||||
Debug.WriteLine("ImageTileSource.LoadImage: " + ex.Message);
|
||||
}
|
||||
|
||||
return image;
|
||||
|
|
@ -218,7 +219,7 @@ namespace MapControl
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Creating tile image failed: {0}", (object)ex.Message);
|
||||
Debug.WriteLine("{0}: {1}", path, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +233,11 @@ namespace MapControl
|
|||
try
|
||||
{
|
||||
var request = HttpWebRequest.CreateHttp(uri);
|
||||
request.UserAgent = HttpUserAgent;
|
||||
|
||||
if (HttpUserAgent != null)
|
||||
{
|
||||
request.UserAgent = HttpUserAgent;
|
||||
}
|
||||
|
||||
using (var response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
|
|
@ -240,23 +245,24 @@ namespace MapControl
|
|||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
responseStream.CopyTo(memoryStream);
|
||||
memoryStream.Position = 0;
|
||||
image = BitmapFrame.Create(memoryStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
}
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
if (cacheKey != null)
|
||||
{
|
||||
SetCachedImage(cacheKey, image, GetExpiration(response.Headers));
|
||||
image = BitmapFrame.Create(memoryStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
|
||||
if (cacheKey != null)
|
||||
{
|
||||
SetCachedImage(cacheKey, memoryStream, GetExpiration(response.Headers));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
Debug.WriteLine("Downloading {0} failed: {1}: {2}", uri, ex.Status, ex.Message);
|
||||
Debug.WriteLine("{0}: {1}: {2}", uri, ex.Status, ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Downloading {0} failed: {1}", uri, ex.Message);
|
||||
Debug.WriteLine("{0}: {1}", uri, ex.Message);
|
||||
}
|
||||
|
||||
return image;
|
||||
|
|
@ -274,34 +280,44 @@ namespace MapControl
|
|||
|
||||
private static bool GetCachedImage(string cacheKey, out BitmapSource image)
|
||||
{
|
||||
image = Cache.Get(cacheKey) as BitmapSource;
|
||||
image = null;
|
||||
|
||||
if (image == null)
|
||||
var buffer = Cache.Get(cacheKey) as byte[];
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
return false;
|
||||
try
|
||||
{
|
||||
using (var memoryStream = new MemoryStream(buffer))
|
||||
{
|
||||
image = BitmapFrame.Create(memoryStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
}
|
||||
|
||||
DateTime expiration = DateTime.MinValue;
|
||||
|
||||
if (buffer.Length >= 16 && Encoding.ASCII.GetString(buffer, buffer.Length - 16, 8) == "EXPIRES:")
|
||||
{
|
||||
expiration = new DateTime(BitConverter.ToInt64(buffer, buffer.Length - 8), DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
return expiration > DateTime.UtcNow;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("{0}: {1}", cacheKey, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
var metadata = (BitmapMetadata)image.Metadata;
|
||||
DateTime expiration;
|
||||
|
||||
// get cache expiration date from BitmapMetadata.DateTaken, must be parsed with CurrentCulture
|
||||
return metadata == null
|
||||
|| metadata.DateTaken == null
|
||||
|| !DateTime.TryParse(metadata.DateTaken, CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out expiration)
|
||||
|| expiration > DateTime.UtcNow;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void SetCachedImage(string cacheKey, BitmapSource image, DateTime expiration)
|
||||
private static void SetCachedImage(string cacheKey, MemoryStream memoryStream, DateTime expiration)
|
||||
{
|
||||
var bitmap = BitmapFrame.Create(image);
|
||||
var metadata = (BitmapMetadata)bitmap.Metadata;
|
||||
memoryStream.Seek(0, SeekOrigin.End);
|
||||
memoryStream.Write(Encoding.ASCII.GetBytes("EXPIRES:"), 0, 8);
|
||||
memoryStream.Write(BitConverter.GetBytes(expiration.Ticks), 0, 8);
|
||||
|
||||
// store cache expiration date in BitmapMetadata.DateTaken
|
||||
metadata.DateTaken = expiration.ToString(CultureInfo.InvariantCulture);
|
||||
metadata.Freeze();
|
||||
bitmap.Freeze();
|
||||
|
||||
Cache.Set(cacheKey, bitmap, new CacheItemPolicy { AbsoluteExpiration = expiration });
|
||||
Cache.Set(cacheKey, memoryStream.ToArray(), new CacheItemPolicy { AbsoluteExpiration = expiration });
|
||||
|
||||
//Debug.WriteLine("Cached {0}, Expires {1}", cacheKey, expiration);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ using System.Windows.Threading;
|
|||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Fills a rectangular area with map tiles from a TileSource.
|
||||
/// Fills the map viewport with map tiles from a TileSource.
|
||||
/// </summary>
|
||||
#if NETFX_CORE
|
||||
[ContentProperty(Name = "TileSource")]
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
return new Uri(uriFormat
|
||||
.Replace("{i}", new string(quadkey[zoomLevel - 1], 1))
|
||||
.Replace("{i}", new string(quadkey, zoomLevel - 1, 1))
|
||||
.Replace("{q}", new string(quadkey)),
|
||||
UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2015 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("2.6.0")]
|
||||
[assembly: AssemblyFileVersion("2.6.0")]
|
||||
[assembly: AssemblyVersion("2.7.0")]
|
||||
[assembly: AssemblyFileVersion("2.7.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue