diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs index f901530c..fa4d1652 100644 --- a/MapControl/Shared/MapBase.cs +++ b/MapControl/Shared/MapBase.cs @@ -31,8 +31,6 @@ namespace MapControl /// public partial class MapBase : MapPanel { - private const double MaximumZoomLevel = 22d; - public static TimeSpan ImageFadeDuration { get; set; } = TimeSpan.FromSeconds(0.1); public static readonly DependencyProperty MapLayerProperty = DependencyProperty.Register( @@ -321,6 +319,7 @@ namespace MapControl if (rotation != 0d) { var heading = (((Heading + rotation) % 360d) + 360d) % 360d; + SetValueInternal(HeadingProperty, heading); SetValueInternal(TargetHeadingProperty, heading); } @@ -328,6 +327,7 @@ namespace MapControl if (scale != 1d) { var zoomLevel = Math.Min(Math.Max(ZoomLevel + Math.Log(scale, 2d), MinZoomLevel), MaxZoomLevel); + SetValueInternal(ZoomLevelProperty, zoomLevel); SetValueInternal(TargetZoomLevelProperty, zoomLevel); } @@ -437,17 +437,16 @@ namespace MapControl private void AdjustCenterProperty(DependencyProperty property, ref Location center) { - if (center == null) - { - center = new Location(); - SetValueInternal(property, center); - } - else if (center.Longitude < -180d || center.Longitude > 180d || + if (center == null || + center.Longitude < -180d || center.Longitude > 180d || center.Latitude < -MapProjection.MaxLatitude || center.Latitude > MapProjection.MaxLatitude) { - center = new Location( - Math.Min(Math.Max(center.Latitude, -MapProjection.MaxLatitude), MapProjection.MaxLatitude), - Location.NormalizeLongitude(center.Longitude)); + center = (center == null) + ? new Location() + : new Location( + Math.Min(Math.Max(center.Latitude, -MapProjection.MaxLatitude), MapProjection.MaxLatitude), + Location.NormalizeLongitude(center.Longitude)); + SetValueInternal(property, center); } } @@ -519,6 +518,7 @@ namespace MapControl if (minZoomLevel < 0d || minZoomLevel > MaxZoomLevel) { minZoomLevel = Math.Min(Math.Max(minZoomLevel, 0d), MaxZoomLevel); + SetValueInternal(MinZoomLevelProperty, minZoomLevel); } @@ -530,9 +530,10 @@ namespace MapControl private void MaxZoomLevelPropertyChanged(double maxZoomLevel) { - if (maxZoomLevel < MinZoomLevel || maxZoomLevel > MaximumZoomLevel) + if (maxZoomLevel < MinZoomLevel) { - maxZoomLevel = Math.Min(Math.Max(maxZoomLevel, MinZoomLevel), MaximumZoomLevel); + maxZoomLevel = MinZoomLevel; + SetValueInternal(MaxZoomLevelProperty, maxZoomLevel); } @@ -547,6 +548,7 @@ namespace MapControl if (zoomLevel < MinZoomLevel || zoomLevel > MaxZoomLevel) { zoomLevel = Math.Min(Math.Max(zoomLevel, MinZoomLevel), MaxZoomLevel); + SetValueInternal(property, zoomLevel); } } @@ -611,6 +613,7 @@ namespace MapControl if (heading < 0d || heading > 360d) { heading = ((heading % 360d) + 360d) % 360d; + SetValueInternal(property, heading); } } @@ -684,7 +687,9 @@ namespace MapControl private void SetValueInternal(DependencyProperty property, object value) { internalPropertyChange = true; + SetValue(property, value); + internalPropertyChange = false; } diff --git a/MapControl/Shared/TileImageLoader.cs b/MapControl/Shared/TileImageLoader.cs index f51315cd..bb43b610 100644 --- a/MapControl/Shared/TileImageLoader.cs +++ b/MapControl/Shared/TileImageLoader.cs @@ -30,11 +30,10 @@ namespace MapControl public static TimeSpan DefaultCacheExpiration { get; set; } = TimeSpan.FromDays(1); /// - /// Format string for creating cache keys from the cacheName argument passed to LoadTilesAsync, - /// the ZoomLevel, XIndex, and Y properties of a Tile, and the image file extension. - /// The default value is "{0}/{1}/{2}/{3}{4}". + /// Maximum expiration time for cached tile images. A transmitted expiration time + /// that exceeds this value is ignored. The default value is ten days. /// - public static string CacheKeyFormat { get; set; } = "{0}/{1}/{2}/{3}{4}"; + public static TimeSpan MaxCacheExpiration { get; set; } = TimeSpan.FromDays(10); private class TileQueue : ConcurrentStack @@ -51,7 +50,7 @@ namespace MapControl } private readonly TileQueue tileQueue = new TileQueue(); - private Func loadTile; + private Func loadTileFunc; private int taskCount; /// @@ -72,11 +71,11 @@ namespace MapControl tileSource.UriFormat.StartsWith("http") && !string.IsNullOrEmpty(cacheName)) { - loadTile = tile => LoadCachedTileAsync(tile, tileSource, cacheName); + loadTileFunc = tile => LoadCachedTileAsync(tile, tileSource, cacheName); } else { - loadTile = tile => LoadTileAsync(tile, tileSource); + loadTileFunc = tile => LoadTileAsync(tile, tileSource); } tileQueue.Enqueue(tiles); @@ -98,7 +97,7 @@ namespace MapControl try { - await loadTile(tile).ConfigureAwait(false); + await loadTileFunc(tile).ConfigureAwait(false); } catch (Exception ex) { @@ -122,7 +121,7 @@ namespace MapControl extension = ".jpg"; } - var cacheKey = string.Format(CacheKeyFormat, cacheName, tile.ZoomLevel, tile.XIndex, tile.Y, extension); + var cacheKey = string.Format("{0}/{1}/{2}/{3}{4}", cacheName, tile.ZoomLevel, tile.XIndex, tile.Y, extension); await LoadCachedTileAsync(tile, uri, cacheKey).ConfigureAwait(false); } @@ -130,7 +129,16 @@ namespace MapControl private static DateTime GetExpiration(TimeSpan? maxAge) { - return DateTime.UtcNow.Add(maxAge ?? DefaultCacheExpiration); + if (!maxAge.HasValue) + { + maxAge = DefaultCacheExpiration; + } + else if (maxAge.Value > MaxCacheExpiration) + { + maxAge = MaxCacheExpiration; + } + + return DateTime.UtcNow.Add(maxAge.Value); } } } diff --git a/MapControl/WPF/ImageFileCache.WPF.cs b/MapControl/WPF/ImageFileCache.WPF.cs index fb528554..2d9016d1 100644 --- a/MapControl/WPF/ImageFileCache.WPF.cs +++ b/MapControl/WPF/ImageFileCache.WPF.cs @@ -169,7 +169,9 @@ namespace MapControl.Caching string path; - if (imageCacheItem.Buffer != null && imageCacheItem.Buffer.Length > 0 && (path = GetPath(key)) != null) + if (imageCacheItem.Buffer != null && + imageCacheItem.Buffer.Length > 0 && + (path = GetPath(key)) != null) { try { @@ -282,7 +284,7 @@ namespace MapControl.Caching { try { - return Path.Combine(rootDirectory, Path.Combine(key.Split('\\', '/', ',', ':', ';'))); + return Path.Combine(rootDirectory, Path.Combine(key.Split('/', ':', ';', ','))); } catch (Exception ex) { @@ -294,14 +296,15 @@ namespace MapControl.Caching private async Task CleanRootDirectory() { - var deletedFileCount = 0; - foreach (var dir in new DirectoryInfo(rootDirectory).EnumerateDirectories()) { - deletedFileCount += await CleanDirectory(dir).ConfigureAwait(false); - } + var deletedFileCount = await CleanDirectory(dir).ConfigureAwait(false); - Debug.WriteLine("ImageFileCache: Cleaned {0} files in {1}", deletedFileCount, rootDirectory); + if (deletedFileCount > 0) + { + Debug.WriteLine("ImageFileCache: Cleaned {0} files in {1}", deletedFileCount, dir); + } + } } private static async Task CleanDirectory(DirectoryInfo directory)