diff --git a/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs b/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs
index 4545fab0..969bf3c2 100644
--- a/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs
+++ b/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("3.2.0")]
-[assembly: AssemblyFileVersion("3.2.0")]
+[assembly: AssemblyVersion("3.3.0")]
+[assembly: AssemblyFileVersion("3.3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs b/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs
index 6402489d..cc33c8ea 100644
--- a/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs
+++ b/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("3.2.0")]
-[assembly: AssemblyFileVersion("3.2.0")]
+[assembly: AssemblyVersion("3.3.0")]
+[assembly: AssemblyFileVersion("3.3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs b/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs
index d0cdf11b..983860e4 100644
--- a/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs
+++ b/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("3.2.0")]
-[assembly: AssemblyFileVersion("3.2.0")]
+[assembly: AssemblyVersion("3.3.0")]
+[assembly: AssemblyFileVersion("3.3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs b/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs
index 0e35675d..7835e5a2 100644
--- a/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs
+++ b/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("3.2.0")]
-[assembly: AssemblyFileVersion("3.2.0")]
+[assembly: AssemblyVersion("3.3.0")]
+[assembly: AssemblyFileVersion("3.3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MapControl/ImageTileSource.Silverlight.WinRT.cs b/MapControl/ImageTileSource.Silverlight.WinRT.cs
index 6c14b103..824d0a5f 100644
--- a/MapControl/ImageTileSource.Silverlight.WinRT.cs
+++ b/MapControl/ImageTileSource.Silverlight.WinRT.cs
@@ -13,9 +13,9 @@ using System.Windows.Media.Imaging;
namespace MapControl
{
///
- /// Provides the image of a map tile. ImageTileSource bypasses image
- /// downloading in TileImageLoader. By overriding the LoadImage method,
- /// an application can provide tile images from an arbitrary source.
+ /// Provides the image of a map tile.
+ /// ImageTileSource bypasses image downloading and optional caching in TileImageLoader.
+ /// By overriding the LoadImage method, an application can provide tile images from an arbitrary source.
///
public class ImageTileSource : TileSource
{
diff --git a/MapControl/MapTileLayer.cs b/MapControl/MapTileLayer.cs
index 5ea442c2..4368d0a2 100644
--- a/MapControl/MapTileLayer.cs
+++ b/MapControl/MapTileLayer.cs
@@ -55,7 +55,7 @@ namespace MapControl
public static readonly DependencyProperty TileSourceProperty = DependencyProperty.Register(
nameof(TileSource), typeof(TileSource), typeof(MapTileLayer),
- new PropertyMetadata(null, (o, e) => ((MapTileLayer)o).ResetTiles()));
+ new PropertyMetadata(null, (o, e) => ((MapTileLayer)o).TileSourcePropertyChanged()));
public static readonly DependencyProperty SourceNameProperty = DependencyProperty.Register(
nameof(SourceName), typeof(string), typeof(MapTileLayer), new PropertyMetadata(null));
@@ -125,7 +125,7 @@ namespace MapControl
}
///
- /// Name of the TileSource. Used as key in a TileLayerCollection and as component of a tile cache key.
+ /// Name of the TileSource. Used as component of a tile cache key.
///
public string SourceName
{
@@ -134,8 +134,7 @@ namespace MapControl
}
///
- /// Description of the MapTileLayer.
- /// Used to display copyright information on top of the map.
+ /// Description of the MapTileLayer. Used to display copyright information on top of the map.
///
public string Description
{
@@ -198,8 +197,7 @@ namespace MapControl
}
///
- /// Optional background brush.
- /// Sets MapBase.Background if not null and the MapTileLayer is the base map layer.
+ /// Optional background brush. Sets MapBase.Background if not null and the MapTileLayer is the base map layer.
///
public Brush MapBackground
{
@@ -208,8 +206,7 @@ namespace MapControl
}
///
- /// Optional foreground brush.
- /// Sets MapBase.Foreground if not null and the MapTileLayer is the base map layer.
+ /// Optional foreground brush. Sets MapBase.Foreground if not null and the MapTileLayer is the base map layer.
///
public Brush MapForeground
{
@@ -287,7 +284,16 @@ namespace MapControl
else
{
TileGrid = null;
- ResetTiles();
+ UpdateTiles();
+ }
+ }
+
+ private void TileSourcePropertyChanged()
+ {
+ if (TileGrid != null)
+ {
+ Tiles.Clear();
+ UpdateTiles();
}
}
@@ -295,8 +301,7 @@ namespace MapControl
{
if (TileGrid == null || e.ProjectionChanged || Math.Abs(e.LongitudeOffset) > 180d)
{
- // update immediately when map projection has changed or map center has moved across 180° longitude
- UpdateTileGrid();
+ UpdateTileGrid(); // update immediately when projection has changed or center has moved across 180° longitude
}
else
{
@@ -314,9 +319,8 @@ namespace MapControl
}
}
- private Point GetTileCenter(double tileScale)
+ private Point GetTileCenter(double tileScale) // map center in tile index coordinates
{
- // map center in tile index coordinates
return new Point(
tileScale * (0.5 + parentMap.Center.Longitude / 360d),
tileScale * (0.5 - WebMercatorProjection.LatitudeToY(parentMap.Center.Latitude) / 360d));
@@ -354,27 +358,7 @@ namespace MapControl
MatrixEx.TranslateScaleRotateTranslate(tileOrigin, scale, parentMap.Heading, viewCenter);
}
- private void ResetTiles()
- {
- Tiles.Clear();
- UpdateTiles();
- }
-
private void UpdateTiles()
- {
- SelectTiles();
-
- Children.Clear();
-
- foreach (var tile in Tiles)
- {
- Children.Add(tile.Image);
- }
-
- TileImageLoader.LoadTiles(this);
- }
-
- private void SelectTiles()
{
var newTiles = new List();
@@ -406,8 +390,7 @@ namespace MapControl
if (equivalentTile != null)
{
- // do not animate to avoid flicker when crossing 180°
- tile.SetImage(equivalentTile.Image.Source, false);
+ tile.SetImage(equivalentTile.Image.Source, false); // do not animate to avoid flicker when crossing 180° longitude
}
}
@@ -418,6 +401,15 @@ namespace MapControl
}
Tiles = newTiles;
+
+ Children.Clear();
+
+ foreach (var tile in Tiles)
+ {
+ Children.Add(tile.Image);
+ }
+
+ TileImageLoader.LoadTiles(this);
}
}
}
diff --git a/MapControl/Properties/AssemblyInfo.cs b/MapControl/Properties/AssemblyInfo.cs
index 91326449..c9a05a9e 100644
--- a/MapControl/Properties/AssemblyInfo.cs
+++ b/MapControl/Properties/AssemblyInfo.cs
@@ -14,8 +14,8 @@ using System.Windows;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("3.2.0")]
-[assembly: AssemblyFileVersion("3.2.0")]
+[assembly: AssemblyVersion("3.3.0")]
+[assembly: AssemblyFileVersion("3.3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MapControl/TileImageLoader.Silverlight.cs b/MapControl/TileImageLoader.Silverlight.cs
index aafc4ec1..9c613dc9 100644
--- a/MapControl/TileImageLoader.Silverlight.cs
+++ b/MapControl/TileImageLoader.Silverlight.cs
@@ -13,7 +13,7 @@ namespace MapControl
///
/// Loads map tile images.
///
- internal class TileImageLoader : ITileImageLoader
+ public class TileImageLoader : ITileImageLoader
{
public void LoadTiles(MapTileLayer tileLayer)
{
diff --git a/MapControl/TileImageLoader.WPF.cs b/MapControl/TileImageLoader.WPF.cs
index a34e06d0..f214efcb 100644
--- a/MapControl/TileImageLoader.WPF.cs
+++ b/MapControl/TileImageLoader.WPF.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -69,11 +68,11 @@ namespace MapControl
{
pendingTiles.Clear();
- var tileStack = tileLayer.Tiles.Where(t => t.Pending).Reverse().ToArray();
+ var tiles = tileLayer.Tiles.Where(t => t.Pending);
- if (tileStack.Length > 0)
+ if (tiles.Any())
{
- pendingTiles.PushRange(tileStack);
+ pendingTiles.PushRange(tiles.Reverse().ToArray());
var tileSource = tileLayer.TileSource;
var sourceName = tileLayer.SourceName;
diff --git a/MapControl/TileImageLoader.WinRT.cs b/MapControl/TileImageLoader.WinRT.cs
index 0b755182..712cab76 100644
--- a/MapControl/TileImageLoader.WinRT.cs
+++ b/MapControl/TileImageLoader.WinRT.cs
@@ -64,21 +64,20 @@ namespace MapControl
{
pendingTiles.Clear();
- var tileSource = tileLayer.TileSource;
- var imageTileSource = tileSource as ImageTileSource;
var tiles = tileLayer.Tiles.Where(t => t.Pending);
- if (imageTileSource != null)
+ if (tiles.Any())
{
- LoadTiles(imageTileSource, tiles);
- }
- else
- {
- var tileStack = tiles.Reverse().ToArray();
+ var tileSource = tileLayer.TileSource;
+ var imageTileSource = tileSource as ImageTileSource;
- if (tileStack.Length > 0)
+ if (imageTileSource != null)
{
- pendingTiles.PushRange(tileStack);
+ LoadTiles(tiles, imageTileSource);
+ }
+ else
+ {
+ pendingTiles.PushRange(tiles.Reverse().ToArray());
var sourceName = tileLayer.SourceName;
var maxDownloads = tileLayer.MaxParallelDownloads;
@@ -98,7 +97,7 @@ namespace MapControl
}
}
- private void LoadTiles(ImageTileSource tileSource, IEnumerable tiles)
+ private void LoadTiles(IEnumerable tiles, ImageTileSource tileSource)
{
foreach (var tile in tiles)
{
@@ -134,7 +133,15 @@ namespace MapControl
if (uri != null)
{
- if (Cache == null || sourceName == null)
+ if (!uri.IsAbsoluteUri)
+ {
+ await LoadImageFromFile(tile, uri.OriginalString);
+ }
+ else if (uri.Scheme == "file")
+ {
+ await LoadImageFromFile(tile, uri.LocalPath);
+ }
+ else if (Cache == null || sourceName == null)
{
await DownloadImage(tile, uri, null);
}
@@ -186,7 +193,14 @@ namespace MapControl
{
if (response.IsSuccessStatusCode)
{
- return await LoadImageFromHttpResponse(response, tile, cacheKey);
+ string tileInfo;
+
+ if (!response.Headers.TryGetValue("X-VE-Tile-Info", out tileInfo) || tileInfo != "no-tile") // set by Bing Maps
+ {
+ await LoadImageFromHttpResponse(response, tile, cacheKey);
+ }
+
+ return true;
}
Debug.WriteLine("{0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
@@ -200,15 +214,8 @@ namespace MapControl
return false;
}
- private async Task LoadImageFromHttpResponse(HttpResponseMessage response, Tile tile, string cacheKey)
+ private async Task LoadImageFromHttpResponse(HttpResponseMessage response, Tile tile, string cacheKey)
{
- string tileInfo;
-
- if (response.Headers.TryGetValue("X-VE-Tile-Info", out tileInfo) && tileInfo == "no-tile") // set by Bing Maps
- {
- return true;
- }
-
using (var stream = new InMemoryRandomAccessStream())
{
using (var content = response.Content)
@@ -219,9 +226,9 @@ namespace MapControl
await stream.FlushAsync();
stream.Seek(0);
- var loaded = await LoadImageFromStream(tile, stream);
+ await LoadImageFromStream(tile, stream);
- if (loaded && cacheKey != null)
+ if (cacheKey != null)
{
var buffer = new Windows.Storage.Streams.Buffer((uint)stream.Size);
@@ -242,14 +249,29 @@ namespace MapControl
await Cache.SetAsync(cacheKey, buffer, DateTime.UtcNow.Add(expiration));
}
-
- return loaded;
}
}
- private async Task LoadImageFromStream(Tile tile, IRandomAccessStream stream)
+ private async Task LoadImageFromFile(Tile tile, string path)
{
- var tcs = new TaskCompletionSource();
+ try
+ {
+ var file = await StorageFile.GetFileFromPathAsync(path);
+
+ using (var stream = await file.OpenReadAsync())
+ {
+ await LoadImageFromStream(tile, stream);
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("{0}: {1}", path, ex.Message);
+ }
+ }
+
+ private async Task LoadImageFromStream(Tile tile, IRandomAccessStream stream)
+ {
+ var tcs = new TaskCompletionSource