diff --git a/MapControl/Shared/MapTileLayer.cs b/MapControl/Shared/MapTileLayer.cs index 35f3b369..04677e9f 100644 --- a/MapControl/Shared/MapTileLayer.cs +++ b/MapControl/Shared/MapTileLayer.cs @@ -29,6 +29,10 @@ namespace MapControl private static readonly Point MapTopLeft = new(-180d * MapProjection.Wgs84MeterPerDegree, 180d * MapProjection.Wgs84MeterPerDegree); + public static readonly DependencyProperty TileSourceProperty = + DependencyPropertyHelper.Register(nameof(TileSource), null, + (layer, oldValue, newValue) => layer.UpdateTileCollection(true)); + public static readonly DependencyProperty MinZoomLevelProperty = DependencyPropertyHelper.Register(nameof(MinZoomLevel), 0); @@ -59,6 +63,15 @@ namespace MapControl public ICollection Tiles { get; private set; } = []; + /// + /// Provides the ImagesSource or image request Uri for map tiles. + /// + public TileSource TileSource + { + get => (TileSource)GetValue(TileSourceProperty); + set => SetValue(TileSourceProperty, value); + } + /// /// Minimum zoom level supported by the MapTileLayer. Default value is 0. /// @@ -129,20 +142,30 @@ namespace MapControl } } - protected override void UpdateTileCollection(bool reset) + protected override void UpdateTileCollection() { - if (ParentMap == null || !SupportedCrsIds.Contains(ParentMap.MapProjection.CrsId)) + UpdateTileCollection(false); + } + + private void UpdateTileCollection(bool tileSourceChanged) + { + if (TileSource == null || ParentMap == null || !SupportedCrsIds.Contains(ParentMap.MapProjection.CrsId)) { CancelLoadTiles(); Children.Clear(); Tiles.Clear(); TileMatrix = null; } - else if (SetTileMatrix() || reset) + else if (SetTileMatrix() || tileSourceChanged) { + if (tileSourceChanged) + { + Tiles.Clear(); + } + UpdateRenderTransform(); - UpdateTiles(reset); - BeginLoadTiles(Tiles, SourceName); + UpdateTiles(); + BeginLoadTiles(Tiles, TileSource, SourceName); } } @@ -177,15 +200,9 @@ namespace MapControl return true; } - private void UpdateTiles(bool reset) + private void UpdateTiles() { var tiles = new ImageTileList(); - - if (reset) - { - Tiles.Clear(); - } - var maxZoomLevel = Math.Min(TileMatrix.ZoomLevel, MaxZoomLevel); if (maxZoomLevel >= MinZoomLevel) diff --git a/MapControl/Shared/TilePyramidLayer.cs b/MapControl/Shared/TilePyramidLayer.cs index 08bdfa98..1475c019 100644 --- a/MapControl/Shared/TilePyramidLayer.cs +++ b/MapControl/Shared/TilePyramidLayer.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; #if WPF using System.Windows; using System.Windows.Controls; @@ -19,7 +18,6 @@ using Microsoft.UI.Xaml.Hosting; using Microsoft.UI.Xaml.Media; #elif AVALONIA using Avalonia.Controls; -using Avalonia.Media; using Brush = Avalonia.Media.IBrush; #endif @@ -27,10 +25,6 @@ namespace MapControl { public abstract class TilePyramidLayer : Panel, IMapLayer { - public static readonly DependencyProperty TileSourceProperty = - DependencyPropertyHelper.Register(nameof(TileSource), null, - (layer, oldValue, newValue) => layer.UpdateTiles(true)); - public static readonly DependencyProperty SourceNameProperty = DependencyPropertyHelper.Register(nameof(SourceName)); @@ -83,15 +77,6 @@ namespace MapControl set => tileImageLoader = value; } - /// - /// Provides map tile URIs or images. - /// - public TileSource TileSource - { - get => (TileSource)GetValue(TileSourceProperty); - set => SetValue(TileSourceProperty, value); - } - /// /// Name of the tile source that is used as component of a tile cache key. /// Tile images are not cached when SourceName is null or empty. @@ -190,12 +175,9 @@ namespace MapControl public abstract IReadOnlyCollection SupportedCrsIds { get; } - protected void BeginLoadTiles(IEnumerable tiles, string cacheName) + protected void BeginLoadTiles(IEnumerable tiles, TileSource tileSource, string cacheName) { - if (TileSource != null && tiles != null && tiles.Any(tile => tile.IsPending)) - { - TileImageLoader.BeginLoadTiles(tiles, TileSource, cacheName, loadingProgress); - } + TileImageLoader.BeginLoadTiles(tiles, tileSource, cacheName, loadingProgress); } protected void CancelLoadTiles() @@ -206,12 +188,12 @@ namespace MapControl protected abstract void UpdateRenderTransform(); - protected abstract void UpdateTileCollection(bool reset); + protected abstract void UpdateTileCollection(); - private void UpdateTiles(bool reset = false) + private void UpdateTiles() { updateTimer.Stop(); - UpdateTileCollection(reset); + UpdateTileCollection(); } private void OnViewportChanged(object sender, ViewportChangedEventArgs e) diff --git a/MapControl/Shared/WmtsCapabilities.cs b/MapControl/Shared/WmtsCapabilities.cs index 4d825239..f28a85c5 100644 --- a/MapControl/Shared/WmtsCapabilities.cs +++ b/MapControl/Shared/WmtsCapabilities.cs @@ -47,7 +47,7 @@ namespace MapControl } else { - throw new ArgumentException($"Invalid Capabilities URI: {uri}"); + throw new ArgumentException($"Invalid Capabilities Uri: {uri}"); } using var stream = xmlStream; diff --git a/MapControl/Shared/WmtsTileLayer.cs b/MapControl/Shared/WmtsTileLayer.cs index fd8d7fe1..ba9ca8ba 100644 --- a/MapControl/Shared/WmtsTileLayer.cs +++ b/MapControl/Shared/WmtsTileLayer.cs @@ -26,8 +26,10 @@ namespace MapControl private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger(typeof(WmtsTileLayer)); public static readonly DependencyProperty CapabilitiesUriProperty = - DependencyPropertyHelper.Register(nameof(CapabilitiesUri), null, - (layer, oldValue, newValue) => layer.TileMatrixSets.Clear()); + DependencyPropertyHelper.Register(nameof(CapabilitiesUri)); + + public static readonly DependencyProperty TileUriTemplateProperty = + DependencyPropertyHelper.Register(nameof(TileUriTemplate)); public static readonly DependencyProperty LayerProperty = DependencyPropertyHelper.Register(nameof(Layer)); @@ -50,7 +52,18 @@ namespace MapControl } /// - /// The Identifier of the Layer that should be displayed. If not set, the first Layer is displayed. + /// The Uri template string used for the UriTemplate property of WmtsTileSource instances. + /// Usually set internally from WmtsCapabilities requested by a Loaded event handler. + /// + public string TileUriTemplate + { + get => (string)GetValue(TileUriTemplateProperty); + set => SetValue(TileUriTemplateProperty, value); + } + + /// + /// The Identifier of the Layer that should be displayed. + /// If not set, the value is defined by WmtsCapabilities. /// public string Layer { @@ -108,10 +121,8 @@ namespace MapControl } } - protected override void UpdateTileCollection(bool reset) + protected override void UpdateTileCollection() { - // reset parameter is ignored here because it is always false. - if (ParentMap == null || !TileMatrixSets.TryGetValue(ParentMap.MapProjection.CrsId, out WmtsTileMatrixSet tileMatrixSet)) { @@ -120,7 +131,11 @@ namespace MapControl } else if (UpdateChildLayers(tileMatrixSet)) { - ((WmtsTileSource)TileSource).TileMatrixSet = tileMatrixSet; + var tileSource = new WmtsTileSource + { + UriTemplate = TileUriTemplate, + TileMatrixSet = tileMatrixSet + }; var cacheName = SourceName; @@ -137,7 +152,7 @@ namespace MapControl } } - BeginLoadTiles(ChildLayers.SelectMany(layer => layer.Tiles), cacheName); + BeginLoadTiles(ChildLayers.SelectMany(layer => layer.Tiles), tileSource, cacheName); } } @@ -216,7 +231,9 @@ namespace MapControl } Layer = capabilities.Layer; - TileSource = new WmtsTileSource { UriTemplate = capabilities.UriTemplate }; + TileUriTemplate = capabilities.UriTemplate; + + UpdateTileCollection(); } catch (Exception ex) {