diff --git a/MBTiles/UWP/MBTiles.UWP.csproj b/MBTiles/UWP/MBTiles.UWP.csproj
index 5efe3731..f937560c 100644
--- a/MBTiles/UWP/MBTiles.UWP.csproj
+++ b/MBTiles/UWP/MBTiles.UWP.csproj
@@ -57,7 +57,7 @@
6.2.12
- 1.0.114.2
+ 1.0.114.3
diff --git a/MBTiles/WPF/MBTiles.WPF.csproj b/MBTiles/WPF/MBTiles.WPF.csproj
index 33b2bf9d..ed4b9afe 100644
--- a/MBTiles/WPF/MBTiles.WPF.csproj
+++ b/MBTiles/WPF/MBTiles.WPF.csproj
@@ -38,7 +38,7 @@
-
+
diff --git a/MapControl/Shared/MapScale.cs b/MapControl/Shared/MapScale.cs
index 9edb88fe..f4eeaff1 100644
--- a/MapControl/Shared/MapScale.cs
+++ b/MapControl/Shared/MapScale.cs
@@ -47,7 +47,7 @@ namespace MapControl
line.SetBinding(Shape.StrokeProperty, this.GetBinding(nameof(Stroke)));
line.SetBinding(Shape.StrokeThicknessProperty, this.GetBinding(nameof(StrokeThickness)));
-#if WINDOWS_UWP
+#if WINUI || WINDOWS_UWP
label.SetBinding(TextBlock.ForegroundProperty, this.GetBinding(nameof(Foreground)));
#endif
Children.Add(line);
diff --git a/MapControl/UWP/Tile.UWP.cs b/MapControl/UWP/Tile.UWP.cs
index 39872633..f2984614 100644
--- a/MapControl/UWP/Tile.UWP.cs
+++ b/MapControl/UWP/Tile.UWP.cs
@@ -3,14 +3,14 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Media;
-using Windows.UI.Xaml.Media.Imaging;
-#else
+#if WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
+#else
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Imaging;
#endif
namespace MapControl
diff --git a/MapControl/UWP/TileImageLoader.UWP.cs b/MapControl/UWP/TileImageLoader.UWP.cs
index 548da7cd..116a7c14 100644
--- a/MapControl/UWP/TileImageLoader.UWP.cs
+++ b/MapControl/UWP/TileImageLoader.UWP.cs
@@ -4,13 +4,8 @@
using System;
using System.Threading.Tasks;
-#if WINDOWS_UWP
using Windows.UI.Core;
using Windows.UI.Xaml.Media;
-#else
-using Microsoft.UI.Dispatching;
-using Microsoft.UI.Xaml.Media;
-#endif
namespace MapControl
{
@@ -70,7 +65,6 @@ namespace MapControl
return SetTileImageAsync(tile, () => tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel));
}
-#if WINDOWS_UWP
public static async Task SetTileImageAsync(Tile tile, Func> loadImageFunc)
{
var tcs = new TaskCompletionSource
+
+
+
+
diff --git a/MapControl/WinUI/TileImageLoader.WinUI.cs b/MapControl/WinUI/TileImageLoader.WinUI.cs
new file mode 100644
index 00000000..7a5d867b
--- /dev/null
+++ b/MapControl/WinUI/TileImageLoader.WinUI.cs
@@ -0,0 +1,88 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2021 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Microsoft.UI.Dispatching;
+using Microsoft.UI.Xaml.Media;
+
+namespace MapControl
+{
+ namespace Caching
+ {
+ public interface IImageCache
+ {
+ Task> GetAsync(string key);
+
+ Task SetAsync(string key, byte[] buffer, DateTime expiration);
+ }
+ }
+
+ public partial class TileImageLoader
+ {
+ ///
+ /// Default folder path where an IImageCache instance may save cached data, i.e. C:\ProgramData\MapControl\TileCache
+ ///
+ public static string DefaultCacheFolder
+ {
+ get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl", "TileCache"); }
+ }
+
+ ///
+ /// The IImageCache implementation used to cache tile images. The default is null.
+ ///
+ public static Caching.IImageCache Cache { get; set; }
+
+
+ private static async Task LoadCachedTileAsync(Tile tile, Uri uri, string cacheKey)
+ {
+ var cacheItem = await Cache.GetAsync(cacheKey).ConfigureAwait(false);
+ var buffer = cacheItem?.Item1;
+
+ if (cacheItem == null || cacheItem.Item2 < DateTime.UtcNow)
+ {
+ var response = await ImageLoader.GetHttpResponseAsync(uri).ConfigureAwait(false);
+
+ if (response != null) // download succeeded
+ {
+ buffer = response.Buffer; // may be null or empty when no tile available, but still be cached
+
+ await Cache.SetAsync(cacheKey, buffer, GetExpiration(response.MaxAge)).ConfigureAwait(false);
+ }
+ }
+ //else System.Diagnostics.Debug.WriteLine("Cached: " + cacheKey);
+
+ if (buffer != null && buffer.Length > 0)
+ {
+ await SetTileImageAsync(tile, () => ImageLoader.LoadImageAsync(buffer)).ConfigureAwait(false);
+ }
+ }
+
+ private static Task LoadTileAsync(Tile tile, TileSource tileSource)
+ {
+ return SetTileImageAsync(tile, () => tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel));
+ }
+
+ public static Task SetTileImageAsync(Tile tile, Func> loadImageFunc)
+ {
+ var tcs = new TaskCompletionSource();
+
+ tile.Image.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
+ {
+ try
+ {
+ tile.SetImage(await loadImageFunc());
+ tcs.TrySetResult();
+ }
+ catch (Exception ex)
+ {
+ tcs.TrySetException(ex);
+ }
+ });
+
+ return tcs.Task;
+ }
+ }
+}
diff --git a/SQLiteCache/Shared/SQLiteCache.cs b/SQLiteCache/Shared/SQLiteCache.cs
index 3a5273c9..1fcecfb8 100644
--- a/SQLiteCache/Shared/SQLiteCache.cs
+++ b/SQLiteCache/Shared/SQLiteCache.cs
@@ -86,7 +86,7 @@ namespace MapControl.Caching
return command;
}
- private SQLiteCommand SetItemCommand(string key, DateTime expiration, byte[] buffer)
+ private SQLiteCommand SetItemCommand(string key, byte[] buffer, DateTime expiration)
{
var command = new SQLiteCommand("insert or replace into items (key, expiration, buffer) values (@key, @exp, @buf)", connection);
command.Parameters.AddWithValue("@key", key);
diff --git a/SQLiteCache/UWP/SQLiteCache.UWP.cs b/SQLiteCache/UWP/SQLiteCache.UWP.cs
index bbedd92c..081b897e 100644
--- a/SQLiteCache/UWP/SQLiteCache.UWP.cs
+++ b/SQLiteCache/UWP/SQLiteCache.UWP.cs
@@ -36,7 +36,7 @@ namespace MapControl.Caching
{
try
{
- using (var command = SetItemCommand(key, expiration, buffer))
+ using (var command = SetItemCommand(key, buffer, expiration))
{
await command.ExecuteNonQueryAsync();
}
diff --git a/SQLiteCache/WPF/SQLiteCache.WPF.cs b/SQLiteCache/WPF/SQLiteCache.WPF.cs
index bc88fa55..a4da23ad 100644
--- a/SQLiteCache/WPF/SQLiteCache.WPF.cs
+++ b/SQLiteCache/WPF/SQLiteCache.WPF.cs
@@ -151,7 +151,7 @@ namespace MapControl.Caching
try
{
- using (var command = SetItemCommand(key, cacheItem.Item2, cacheItem.Item1))
+ using (var command = SetItemCommand(key, cacheItem.Item1, cacheItem.Item2))
{
command.ExecuteNonQuery();
}
diff --git a/SampleApps/WinUiApp/MainWindow.xaml.cs b/SampleApps/WinUiApp/MainWindow.xaml.cs
index 9dc0f5ae..3e825bc4 100644
--- a/SampleApps/WinUiApp/MainWindow.xaml.cs
+++ b/SampleApps/WinUiApp/MainWindow.xaml.cs
@@ -19,11 +19,14 @@ namespace WinUiApp
{
ImageLoader.HttpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control Test Application");
- var appData = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl");
+ var bingMapsApiKeyFile = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl", "BingMapsApiKey.txt");
- TileImageLoader.Cache = new ImageFileCache(Path.Combine(appData, "TileCache"));
- BingMapsTileLayer.ApiKey = File.ReadAllText(Path.Combine(appData, "BingMapsApiKey.txt"))?.Trim();
+ BingMapsTileLayer.ApiKey = File.ReadAllText(bingMapsApiKeyFile)?.Trim();
+
+ TileImageLoader.Cache = new ImageFileCache(TileImageLoader.DefaultCacheFolder);
+ //TileImageLoader.Cache = new FileDbCache(TileImageLoader.DefaultCacheFolder);
+ //TileImageLoader.Cache = new SQLiteCache(TileImageLoader.DefaultCacheFolder);
}
catch (Exception ex)
{