mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 7.3. Added tile and map image progress reporting.
This commit is contained in:
parent
b423cc2d36
commit
3119c0fc9b
|
|
@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.2.1")]
|
||||
[assembly: AssemblyFileVersion("7.2.1")]
|
||||
[assembly: AssemblyVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<RootNamespace>MapControl.Caching</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control FileDbCache Library for WPF</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<RootNamespace>MapControl.Caching</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control FileDbCache Library for WinUI</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.2.1")]
|
||||
[assembly: AssemblyFileVersion("7.2.1")]
|
||||
[assembly: AssemblyVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<RootNamespace>MapControl.MBTiles</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control MBTiles Library for WPF</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<RootNamespace>MapControl.MBTiles</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control MBTiles Library for WinUI</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace MapControl
|
|||
public static HttpClient HttpClient { get; set; } = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
|
||||
|
||||
|
||||
public static async Task<ImageSource> LoadImageAsync(Uri uri)
|
||||
public static async Task<ImageSource> LoadImageAsync(Uri uri, IProgress<double> progress = null)
|
||||
{
|
||||
ImageSource image = null;
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ namespace MapControl
|
|||
}
|
||||
else if (uri.Scheme == "http" || uri.Scheme == "https")
|
||||
{
|
||||
var response = await GetHttpResponseAsync(uri);
|
||||
var response = await GetHttpResponseAsync(uri, progress);
|
||||
|
||||
if (response != null && response.Buffer != null)
|
||||
{
|
||||
|
|
@ -73,10 +73,12 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
internal static async Task<HttpResponse> GetHttpResponseAsync(Uri uri)
|
||||
internal static async Task<HttpResponse> GetHttpResponseAsync(Uri uri, IProgress<double> progress = null)
|
||||
{
|
||||
HttpResponse response = null;
|
||||
|
||||
progress?.Report(0d);
|
||||
|
||||
try
|
||||
{
|
||||
using (var responseMessage = await HttpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
|
||||
|
|
@ -85,10 +87,12 @@ namespace MapControl
|
|||
{
|
||||
byte[] buffer = null;
|
||||
|
||||
// check for possibly unavailable Bing Maps tile
|
||||
//
|
||||
if (!responseMessage.Headers.TryGetValues("X-VE-Tile-Info", out IEnumerable<string> tileInfo) ||
|
||||
!tileInfo.Contains("no-tile"))
|
||||
{
|
||||
buffer = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
|
||||
buffer = await ReadAsByteArrayAsync(responseMessage.Content, progress).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
response = new HttpResponse(buffer, responseMessage.Headers.CacheControl?.MaxAge);
|
||||
|
|
@ -104,7 +108,39 @@ namespace MapControl
|
|||
Debug.WriteLine($"ImageLoader: {uri}: {ex.Message}");
|
||||
}
|
||||
|
||||
progress?.Report(1d);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private static async Task<byte[]> ReadAsByteArrayAsync(HttpContent content, IProgress<double> progress)
|
||||
{
|
||||
if (progress == null || !content.Headers.ContentLength.HasValue)
|
||||
{
|
||||
return await content.ReadAsByteArrayAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var length = (int)content.Headers.ContentLength.Value;
|
||||
var buffer = new byte[length];
|
||||
|
||||
using (var stream = await content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
int offset = 0;
|
||||
int read;
|
||||
|
||||
while (offset < length &&
|
||||
(read = await stream.ReadAsync(buffer, offset, length - offset).ConfigureAwait(false)) > 0)
|
||||
{
|
||||
offset += read;
|
||||
|
||||
if (offset < length) // 1.0 reported by caller
|
||||
{
|
||||
progress.Report((double)offset / length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -54,11 +54,17 @@ namespace MapControl
|
|||
public static readonly DependencyProperty MapForegroundProperty = DependencyProperty.Register(
|
||||
nameof(MapForeground), typeof(Brush), typeof(MapImageLayer), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty LoadingProgressProperty = DependencyProperty.Register(
|
||||
nameof(LoadingProgress), typeof(double), typeof(MapImageLayer), new PropertyMetadata(1d));
|
||||
|
||||
private readonly Progress<double> imageProgress;
|
||||
private readonly DispatcherTimer updateTimer;
|
||||
private bool updateInProgress;
|
||||
|
||||
public MapImageLayer()
|
||||
{
|
||||
imageProgress = new Progress<double>(p => LoadingProgress = p);
|
||||
|
||||
updateTimer = this.CreateTimer(UpdateInterval);
|
||||
updateTimer.Tick += async (s, e) => await UpdateImageAsync();
|
||||
}
|
||||
|
|
@ -119,13 +125,20 @@ namespace MapControl
|
|||
set { SetValue(MapForegroundProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the progress of the ImageLoader as a double value between 0 and 1.
|
||||
/// </summary>
|
||||
public double LoadingProgress
|
||||
{
|
||||
get { return (double)GetValue(LoadingProgressProperty); }
|
||||
private set { SetValue(LoadingProgressProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current BoundingBox
|
||||
/// </summary>
|
||||
public BoundingBox BoundingBox { get; private set; }
|
||||
|
||||
protected abstract Task<ImageSource> GetImageAsync();
|
||||
|
||||
protected override void SetParentMap(MapBase map)
|
||||
{
|
||||
if (map == null)
|
||||
|
|
@ -165,38 +178,43 @@ namespace MapControl
|
|||
|
||||
protected async Task UpdateImageAsync()
|
||||
{
|
||||
updateTimer.Stop();
|
||||
|
||||
if (updateInProgress)
|
||||
if (updateInProgress) // update image on next tick
|
||||
{
|
||||
updateTimer.Run(); // update image on next timer tick
|
||||
updateTimer.Run(); // start timer if not running
|
||||
}
|
||||
else if (ParentMap != null && ParentMap.RenderSize.Width > 0 && ParentMap.RenderSize.Height > 0)
|
||||
else
|
||||
{
|
||||
updateInProgress = true;
|
||||
updateTimer.Stop();
|
||||
|
||||
UpdateBoundingBox();
|
||||
|
||||
ImageSource image = null;
|
||||
|
||||
if (BoundingBox != null)
|
||||
if (ParentMap != null && ParentMap.RenderSize.Width > 0 && ParentMap.RenderSize.Height > 0)
|
||||
{
|
||||
try
|
||||
updateInProgress = true;
|
||||
|
||||
UpdateBoundingBox();
|
||||
|
||||
ImageSource image = null;
|
||||
|
||||
if (BoundingBox != null)
|
||||
{
|
||||
image = await GetImageAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"MapImageLayer: {ex.Message}");
|
||||
try
|
||||
{
|
||||
image = await GetImageAsync(imageProgress);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"MapImageLayer: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
SwapImages(image);
|
||||
|
||||
updateInProgress = false;
|
||||
}
|
||||
|
||||
SwapImages(image);
|
||||
|
||||
updateInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Task<ImageSource> GetImageAsync(IProgress<double> progress);
|
||||
|
||||
private void UpdateBoundingBox()
|
||||
{
|
||||
var width = ParentMap.RenderSize.Width * RelativeImageSize;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ namespace MapControl
|
|||
{
|
||||
public interface ITileImageLoader
|
||||
{
|
||||
IProgress<double> Progress { get; set; }
|
||||
|
||||
TileSource TileSource { get; }
|
||||
|
||||
Task LoadTiles(IEnumerable<Tile> tiles, TileSource tileSource, string cacheName);
|
||||
|
|
@ -58,13 +60,19 @@ namespace MapControl
|
|||
public static readonly DependencyProperty MapForegroundProperty = DependencyProperty.Register(
|
||||
nameof(MapForeground), typeof(Brush), typeof(MapTileLayerBase), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty LoadingProgressProperty = DependencyProperty.Register(
|
||||
nameof(LoadingProgress), typeof(double), typeof(MapTileLayerBase), new PropertyMetadata(1d,
|
||||
(o, e) => { System.Diagnostics.Debug.WriteLine("LoadingProgress = {0:P0}", e.NewValue); }));
|
||||
|
||||
private readonly DispatcherTimer updateTimer;
|
||||
private MapBase parentMap;
|
||||
|
||||
protected MapTileLayerBase(ITileImageLoader tileImageLoader)
|
||||
{
|
||||
RenderTransform = new MatrixTransform();
|
||||
|
||||
TileImageLoader = tileImageLoader;
|
||||
TileImageLoader.Progress = new Progress<double>(p => LoadingProgress = p);
|
||||
|
||||
updateTimer = this.CreateTimer(UpdateInterval);
|
||||
updateTimer.Tick += async (s, e) => await Update();
|
||||
|
|
@ -149,6 +157,15 @@ namespace MapControl
|
|||
set { SetValue(MapForegroundProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the progress of the TileImageLoader as a double value between 0 and 1.
|
||||
/// </summary>
|
||||
public double LoadingProgress
|
||||
{
|
||||
get { return (double)GetValue(LoadingProgressProperty); }
|
||||
private set { SetValue(LoadingProgressProperty, value); }
|
||||
}
|
||||
|
||||
public MapBase ParentMap
|
||||
{
|
||||
get { return parentMap; }
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Diagnostics;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MapControl
|
||||
|
|
@ -18,6 +19,35 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public partial class TileImageLoader : ITileImageLoader
|
||||
{
|
||||
private class TileQueue : ConcurrentStack<Tile>
|
||||
{
|
||||
public TileQueue(IEnumerable<Tile> tiles)
|
||||
: base(tiles.Where(tile => tile.Pending).Reverse())
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsCanceled { get; private set; }
|
||||
|
||||
public bool TryDequeue(out Tile tile)
|
||||
{
|
||||
tile = null;
|
||||
|
||||
if (IsCanceled || !TryPop(out tile))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tile.Pending = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
IsCanceled = true;
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of parallel tile loading tasks. The default value is 4.
|
||||
/// </summary>
|
||||
|
|
@ -35,12 +65,19 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public static TimeSpan MaxCacheExpiration { get; set; } = TimeSpan.FromDays(10);
|
||||
|
||||
/// <summary>
|
||||
/// Reports tile loading process as double value between 0 and 1.
|
||||
/// </summary>
|
||||
public IProgress<double> Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current TileSource, passed to the most recent LoadTiles call.
|
||||
/// </summary>
|
||||
public TileSource TileSource { get; private set; }
|
||||
|
||||
private ConcurrentStack<Tile> pendingTiles;
|
||||
private TileQueue pendingTiles;
|
||||
private int progressTotal;
|
||||
private int progressLoaded;
|
||||
|
||||
/// <summary>
|
||||
/// Loads all pending tiles from the tiles collection.
|
||||
|
|
@ -49,39 +86,47 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public Task LoadTiles(IEnumerable<Tile> tiles, TileSource tileSource, string cacheName)
|
||||
{
|
||||
pendingTiles?.Clear(); // stop processing the current queue
|
||||
pendingTiles?.Cancel();
|
||||
|
||||
TileSource = tileSource;
|
||||
|
||||
if (tileSource != null)
|
||||
{
|
||||
pendingTiles = new ConcurrentStack<Tile>(tiles.Where(tile => tile.Pending).Reverse());
|
||||
pendingTiles = new TileQueue(tiles);
|
||||
|
||||
var numTasks = Math.Min(pendingTiles.Count, MaxLoadTasks);
|
||||
|
||||
if (numTasks > 0)
|
||||
{
|
||||
if (Progress != null)
|
||||
{
|
||||
progressTotal = pendingTiles.Count;
|
||||
progressLoaded = 0;
|
||||
Progress.Report(0d);
|
||||
}
|
||||
|
||||
if (Cache == null || tileSource.UriFormat == null || !tileSource.UriFormat.StartsWith("http"))
|
||||
{
|
||||
cacheName = null; // no tile caching
|
||||
}
|
||||
|
||||
var tasks = Enumerable.Range(0, numTasks)
|
||||
.Select(_ => Task.Run(() => LoadPendingTiles(pendingTiles, tileSource, cacheName)));
|
||||
|
||||
return Task.WhenAll(tasks);
|
||||
return Task.WhenAll(Enumerable.Range(0, numTasks).Select(
|
||||
_ => Task.Run(() => LoadPendingTiles(pendingTiles, tileSource, cacheName))));
|
||||
}
|
||||
}
|
||||
|
||||
if (Progress != null && progressLoaded < progressTotal)
|
||||
{
|
||||
Progress.Report(1d);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static async Task LoadPendingTiles(ConcurrentStack<Tile> pendingTiles, TileSource tileSource, string cacheName)
|
||||
private async Task LoadPendingTiles(TileQueue tileQueue, TileSource tileSource, string cacheName)
|
||||
{
|
||||
while (pendingTiles.TryPop(out var tile))
|
||||
while (tileQueue.TryDequeue(out var tile))
|
||||
{
|
||||
tile.Pending = false;
|
||||
|
||||
try
|
||||
{
|
||||
await LoadTile(tile, tileSource, cacheName).ConfigureAwait(false);
|
||||
|
|
@ -90,6 +135,13 @@ namespace MapControl
|
|||
{
|
||||
Debug.WriteLine($"TileImageLoader: {tile.ZoomLevel}/{tile.XIndex}/{tile.Y}: {ex.Message}");
|
||||
}
|
||||
|
||||
if (Progress != null && !tileQueue.IsCanceled)
|
||||
{
|
||||
Interlocked.Increment(ref progressLoaded);
|
||||
|
||||
Progress.Report((double)progressLoaded / progressTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,14 @@ namespace MapControl
|
|||
|
||||
public static readonly DependencyProperty LayersProperty = DependencyProperty.Register(
|
||||
nameof(Layers), typeof(string), typeof(WmsImageLayer),
|
||||
new PropertyMetadata(null, async (o, e) => await ((WmsImageLayer)o).UpdateImageAsync()));
|
||||
new PropertyMetadata(null,
|
||||
async (o, e) =>
|
||||
{
|
||||
if (e.OldValue != null) // ignore initial property change from GetImageAsync
|
||||
{
|
||||
await ((WmsImageLayer)o).UpdateImageAsync();
|
||||
}
|
||||
}));
|
||||
|
||||
public static readonly DependencyProperty StylesProperty = DependencyProperty.Register(
|
||||
nameof(Styles), typeof(string), typeof(WmsImageLayer),
|
||||
|
|
@ -187,7 +194,7 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Loads an ImageSource from the URL returned by GetMapRequestUri().
|
||||
/// </summary>
|
||||
protected override async Task<ImageSource> GetImageAsync()
|
||||
protected override async Task<ImageSource> GetImageAsync(IProgress<double> progress)
|
||||
{
|
||||
ImageSource image = null;
|
||||
|
||||
|
|
@ -203,7 +210,7 @@ namespace MapControl
|
|||
|
||||
if (!string.IsNullOrEmpty(uri))
|
||||
{
|
||||
image = await ImageLoader.LoadImageAsync(new Uri(uri));
|
||||
image = await ImageLoader.LoadImageAsync(new Uri(uri), progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.2.1")]
|
||||
[assembly: AssemblyFileVersion("7.2.1")]
|
||||
[assembly: AssemblyVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<RootNamespace>MapControl</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control Library for WPF</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// © 2022 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -28,7 +29,7 @@ namespace MapControl
|
|||
set { SetValue(ItemsSourceProperty, value); }
|
||||
}
|
||||
|
||||
protected override async Task<ImageSource> GetImageAsync()
|
||||
protected override async Task<ImageSource> GetImageAsync(IProgress<double> progress)
|
||||
{
|
||||
ImageSource image = null;
|
||||
var projection = ParentMap?.MapProjection;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<RootNamespace>MapControl</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control Library for WinUI</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.2.1")]
|
||||
[assembly: AssemblyFileVersion("7.2.1")]
|
||||
[assembly: AssemblyVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<RootNamespace>MapControl.Projections</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control Projections Library for WPF</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<RootNamespace>MapControl.Projections</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control Projections Library for WinUI</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.2.1")]
|
||||
[assembly: AssemblyFileVersion("7.2.1")]
|
||||
[assembly: AssemblyVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<RootNamespace>MapControl.UiTools</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control UI Tools Library for WPF</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<RootNamespace>MapControl.UiTools</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control UI Tools Library for WinUI</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.2.1")]
|
||||
[assembly: AssemblyFileVersion("7.2.1")]
|
||||
[assembly: AssemblyVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<RootNamespace>MapControl.Caching</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control SQLiteCache Library for WPF</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<RootNamespace>MapControl.Caching</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control SQLiteCache Library for WinUI</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<RootNamespace>ProjectionDemo</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control Projection Demo Application</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -13,11 +13,18 @@ using System.Windows.Data;
|
|||
|
||||
namespace SampleApplication
|
||||
{
|
||||
public class HeadingToVisibilityConverter : IValueConverter
|
||||
public class DoubleToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return (double)value != 0d ? Visibility.Visible : Visibility.Collapsed;
|
||||
if (!(parameter is double p))
|
||||
{
|
||||
p = double.Parse(parameter.ToString());
|
||||
}
|
||||
|
||||
//System.Diagnostics.Debug.WriteLine((double)value);
|
||||
|
||||
return (double)value != p ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@
|
|||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<local:DoubleToVisibilityConverter x:Key="DoubleToVisibilityConverter"/>
|
||||
</Grid.Resources>
|
||||
|
||||
<Grid.DataContext>
|
||||
|
|
@ -214,14 +216,8 @@
|
|||
Maximum="{Binding MaxZoomLevel, ElementName=map}"
|
||||
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
|
||||
|
||||
<Button Margin="2" Padding="8" ToolTipService.ToolTip="Reset Heading" Click="ResetHeadingButtonClick">
|
||||
<Button.Visibility>
|
||||
<Binding Path="Heading" ElementName="map">
|
||||
<Binding.Converter>
|
||||
<local:HeadingToVisibilityConverter/>
|
||||
</Binding.Converter>
|
||||
</Binding>
|
||||
</Button.Visibility>
|
||||
<Button Margin="2" Padding="8" ToolTipService.ToolTip="Reset Heading" Click="ResetHeadingButtonClick"
|
||||
Visibility="{Binding Heading, ElementName=map, Converter={StaticResource DoubleToVisibilityConverter}, ConverterParameter=0}">
|
||||
<FontIcon Glyph=""/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.2.1")]
|
||||
[assembly: AssemblyFileVersion("7.2.1")]
|
||||
[assembly: AssemblyVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@
|
|||
</Setter>
|
||||
</Style>
|
||||
|
||||
<local:DoubleToVisibilityConverter x:Key="DoubleToVisibilityConverter"/>
|
||||
</Grid.Resources>
|
||||
|
||||
<Grid.DataContext>
|
||||
|
|
@ -112,10 +113,15 @@
|
|||
</map:Pushpin>
|
||||
</map:Map>
|
||||
|
||||
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#AFFFFFFF">
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#AFFFFFFF">
|
||||
<ProgressBar Width="100" Height="10" Margin="4,2" Maximum="1"
|
||||
Value="{Binding MapLayer.LoadingProgress, ElementName=map}"
|
||||
Visibility="{Binding Value, RelativeSource={RelativeSource Self}, Converter={StaticResource DoubleToVisibilityConverter}, ConverterParameter=1}"/>
|
||||
|
||||
<TextBlock Margin="4,2" FontSize="10"
|
||||
local:HyperlinkText.InlinesSource="{Binding MapLayer.Description, ElementName=map}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<Border HorizontalAlignment="Center" VerticalAlignment="Top" Margin="4"
|
||||
Background="#AFFFFFFF" IsHitTestVisible="False">
|
||||
|
|
@ -214,14 +220,8 @@
|
|||
Maximum="{Binding MaxZoomLevel, ElementName=map}"
|
||||
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
|
||||
|
||||
<Button Margin="2" Padding="8" ToolTipService.ToolTip="Reset Heading" Click="ResetHeadingButtonClick">
|
||||
<Button.Visibility>
|
||||
<Binding Path="Heading" ElementName="map">
|
||||
<Binding.Converter>
|
||||
<local:HeadingToVisibilityConverter/>
|
||||
</Binding.Converter>
|
||||
</Binding>
|
||||
</Button.Visibility>
|
||||
<Button Margin="2" Padding="8" ToolTipService.ToolTip="Reset Heading" Click="ResetHeadingButtonClick"
|
||||
Visibility="{Binding Heading, ElementName=map, Converter={StaticResource DoubleToVisibilityConverter}, ConverterParameter=0}">
|
||||
<FontIcon Glyph=""/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<RootNamespace>SampleApplication</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control WinUI Sample Application</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<AnalysisLevel>none</AnalysisLevel>
|
||||
|
|
|
|||
|
|
@ -138,10 +138,26 @@
|
|||
<map:Pushpin AutoCollapse="True" Location="53.5,8.2" Content="N 53°30' E 8°12'"/>
|
||||
</map:Map>
|
||||
|
||||
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#AFFFFFFF">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#AFFFFFFF">
|
||||
<ProgressBar Width="100" Height="8" Margin="4,2" VerticalAlignment="Center" Maximum="1"
|
||||
Value="{Binding MapLayer.LoadingProgress, ElementName=map}">
|
||||
<ProgressBar.Style>
|
||||
<Style TargetType="ProgressBar">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Value" Value="0">
|
||||
<Setter Property="IsIndeterminate" Value="True"/>
|
||||
</Trigger>
|
||||
<Trigger Property="Value" Value="1">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ProgressBar.Style>
|
||||
</ProgressBar>
|
||||
|
||||
<TextBlock Margin="4,2" FontSize="10"
|
||||
local:HyperlinkText.InlinesSource="{Binding MapLayer.Description, ElementName=map}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<local:OutlinedText
|
||||
x:Name="mouseLocation" Margin="4" FontFamily="Consolas"
|
||||
|
|
@ -191,13 +207,15 @@
|
|||
|
||||
<Button Margin="2" Padding="8" ToolTip="Reset Heading" Click="ResetHeadingButtonClick"
|
||||
FontSize="20" FontFamily="Segoe MDL2 Assets" Content="">
|
||||
<Button.Visibility>
|
||||
<Binding Path="Heading" ElementName="map">
|
||||
<Binding.Converter>
|
||||
<local:HeadingToVisibilityConverter/>
|
||||
</Binding.Converter>
|
||||
</Binding>
|
||||
</Button.Visibility>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Heading, ElementName=map}" Value="0">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<RootNamespace>SampleApplication</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control WPF Sample Application</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.2.1</Version>
|
||||
<Version>7.3.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<DefineConstants></DefineConstants>
|
||||
|
|
|
|||
Loading…
Reference in a new issue