.NET 9, including UWP

This commit is contained in:
ClemensFischer 2025-09-14 21:02:21 +02:00
parent 3526438f58
commit cf0f4645d4
56 changed files with 484 additions and 1206 deletions

View file

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>AVALONIA</DefineConstants>
<RootNamespace>MapControl</RootNamespace>
@ -16,8 +16,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.3.5" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.8" />
<PackageReference Include="Avalonia" Version="11.3.6" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.9" />
</ItemGroup>
</Project>

View file

@ -63,7 +63,7 @@ namespace MapControl
private static string QueryString(ushort tag) => $"/ifd/{{ushort={tag}}}";
private static ILogger logger;
private static ILogger Logger => logger ?? (logger = ImageLoader.LoggerFactory?.CreateLogger(nameof(GeoImage)));
private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger<GroundOverlay>();
public static readonly DependencyProperty SourcePathProperty =
DependencyPropertyHelper.RegisterAttached<string>("SourcePath", typeof(GeoImage), null,
@ -158,33 +158,32 @@ namespace MapControl
private static async Task<Matrix> ReadWorldFileMatrix(string worldFilePath)
{
using (var fileStream = File.OpenRead(worldFilePath))
using (var streamReader = new StreamReader(fileStream))
using var fileStream = File.OpenRead(worldFilePath);
using var streamReader = new StreamReader(fileStream);
var parameters = new double[6];
var index = 0;
string line;
while (index < 6 &&
(line = await streamReader.ReadLineAsync()) != null &&
double.TryParse(line, NumberStyles.Float, CultureInfo.InvariantCulture, out double parameter))
{
var parameters = new double[6];
var index = 0;
string line;
while (index < 6 &&
(line = await streamReader.ReadLineAsync()) != null &&
double.TryParse(line, NumberStyles.Float, CultureInfo.InvariantCulture, out double parameter))
{
parameters[index++] = parameter;
}
if (index != 6)
{
throw new ArgumentException($"Insufficient number of parameters in world file {worldFilePath}.");
}
return new Matrix(
parameters[0], // line 1: A or M11
parameters[1], // line 2: D or M12
parameters[2], // line 3: B or M21
parameters[3], // line 4: E or M22
parameters[4], // line 5: C or OffsetX
parameters[5]); // line 6: F or OffsetY
parameters[index++] = parameter;
}
if (index != 6)
{
throw new ArgumentException($"Insufficient number of parameters in world file {worldFilePath}.");
}
return new Matrix(
parameters[0], // line 1: A or M11
parameters[1], // line 2: D or M12
parameters[2], // line 3: B or M21
parameters[3], // line 4: E or M22
parameters[4], // line 5: C or OffsetX
parameters[5]); // line 6: F or OffsetY
}
private static MapProjection GetProjection(short[] geoKeyDirectory)

View file

@ -52,23 +52,22 @@ namespace MapControl
if (entry != null)
{
using (var memoryStream = new MemoryStream((int)entry.Length))
using var memoryStream = new MemoryStream((int)entry.Length);
using (var zipStream = entry.Open())
{
using (var zipStream = entry.Open())
{
zipStream.CopyTo(memoryStream); // can't use CopyToAsync with ZipArchive
}
memoryStream.Seek(0, SeekOrigin.Begin);
Image.Source = await ImageLoader.LoadImageAsync(memoryStream);
zipStream.CopyTo(memoryStream); // can't use CopyToAsync with ZipArchive
}
memoryStream.Seek(0, SeekOrigin.Begin);
Image.Source = await ImageLoader.LoadImageAsync(memoryStream);
}
}
}
private static ILogger logger;
private static ILogger Logger => logger ?? (logger = ImageLoader.LoggerFactory?.CreateLogger<GroundOverlay>());
private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger<GroundOverlay>();
public static readonly DependencyProperty SourcePathProperty =
DependencyPropertyHelper.Register<GroundOverlay, string>(nameof(SourcePath), null,
@ -127,20 +126,19 @@ namespace MapControl
private static async Task<List<ImageOverlay>> LoadImageOverlaysFromArchive(string archiveFilePath)
{
using (var archive = ZipFile.OpenRead(archiveFilePath))
using var archive = ZipFile.OpenRead(archiveFilePath);
var docEntry = archive.GetEntry("doc.kml") ??
archive.Entries.FirstOrDefault(e => e.Name.EndsWith(".kml")) ??
throw new ArgumentException($"No KML entry found in {archiveFilePath}.");
XDocument document;
using (var docStream = docEntry.Open())
{
var docEntry = archive.GetEntry("doc.kml") ??
archive.Entries.FirstOrDefault(e => e.Name.EndsWith(".kml")) ??
throw new ArgumentException($"No KML entry found in {archiveFilePath}.");
XDocument document;
using (var docStream = docEntry.Open())
{
document = await LoadXDocument(docStream);
}
return await LoadImageOverlays(document, imageOverlay => imageOverlay.LoadImage(archive));
document = await LoadXDocument(docStream);
}
return await LoadImageOverlays(document, imageOverlay => imageOverlay.LoadImage(archive));
}
private static async Task<List<ImageOverlay>> LoadImageOverlaysFromFile(string docFilePath)

View file

@ -326,34 +326,30 @@ namespace MapControl.Caching
private static byte[] ReadAllBytes(FileInfo file)
{
using (var stream = file.OpenRead())
using var stream = file.OpenRead();
var buffer = new byte[stream.Length];
var offset = 0;
while (offset < buffer.Length)
{
var buffer = new byte[stream.Length];
var offset = 0;
while (offset < buffer.Length)
{
offset += stream.Read(buffer, offset, buffer.Length - offset);
}
return buffer;
offset += stream.Read(buffer, offset, buffer.Length - offset);
}
return buffer;
}
private static async Task<byte[]> ReadAllBytes(FileInfo file, CancellationToken token)
{
using (var stream = file.OpenRead())
using var stream = file.OpenRead();
var buffer = new byte[stream.Length];
var offset = 0;
while (offset < buffer.Length)
{
var buffer = new byte[stream.Length];
var offset = 0;
while (offset < buffer.Length)
{
offset += await stream.ReadAsync(buffer, offset, buffer.Length - offset, token).ConfigureAwait(false);
}
return buffer;
offset += await stream.ReadAsync(buffer, offset, buffer.Length - offset, token).ConfigureAwait(false);
}
return buffer;
}
private static void SetExpiration(FileInfo file, DistributedCacheEntryOptions options)

View file

@ -16,7 +16,7 @@ namespace MapControl
public static partial class ImageLoader
{
private static ILogger logger;
private static ILogger Logger => logger ?? (logger = LoggerFactory?.CreateLogger(typeof(ImageLoader)));
private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger<GroundOverlay>();
public static ILoggerFactory LoggerFactory { get; set; }
@ -33,10 +33,9 @@ namespace MapControl
public static async Task<ImageSource> LoadImageAsync(byte[] buffer)
{
using (var stream = new MemoryStream(buffer))
{
return await LoadImageAsync(stream);
}
using var stream = new MemoryStream(buffer);
return await LoadImageAsync(stream);
}
public static async Task<ImageSource> LoadImageAsync(Uri uri, IProgress<double> progress = null)
@ -84,25 +83,24 @@ namespace MapControl
{
var completionOptions = progress != null ? HttpCompletionOption.ResponseHeadersRead : HttpCompletionOption.ResponseContentRead;
using (var responseMessage = await HttpClient.GetAsync(uri, completionOptions).ConfigureAwait(false))
{
if (responseMessage.IsSuccessStatusCode)
{
if (progress != null && responseMessage.Content.Headers.ContentLength.HasValue)
{
buffer = await ReadAsByteArray(responseMessage.Content, progress).ConfigureAwait(false);
}
else
{
buffer = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
}
using var responseMessage = await HttpClient.GetAsync(uri, completionOptions).ConfigureAwait(false);
maxAge = responseMessage.Headers.CacheControl?.MaxAge;
if (responseMessage.IsSuccessStatusCode)
{
if (progress != null && responseMessage.Content.Headers.ContentLength.HasValue)
{
buffer = await ReadAsByteArray(responseMessage.Content, progress).ConfigureAwait(false);
}
else
{
Logger?.LogWarning("{status} ({reason}) from {uri}", (int)responseMessage.StatusCode, responseMessage.ReasonPhrase, uri);
buffer = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
}
maxAge = responseMessage.Headers.CacheControl?.MaxAge;
}
else
{
Logger?.LogWarning("{status} ({reason}) from {uri}", (int)responseMessage.StatusCode, responseMessage.ReasonPhrase, uri);
}
}
catch (TaskCanceledException)

View file

@ -23,7 +23,7 @@ namespace MapControl
public class TileImageLoader : ITileImageLoader
{
private static ILogger logger;
private static ILogger Logger => logger ?? (logger = ImageLoader.LoggerFactory?.CreateLogger<TileImageLoader>());
private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger<GroundOverlay>();
/// <summary>
/// Default folder path where a persistent cache implementation may save data, i.e. "C:\ProgramData\MapControl\TileCache".

View file

@ -26,7 +26,7 @@ namespace MapControl
public class WmsImageLayer : MapImageLayer
{
private static ILogger logger;
private static ILogger Logger => logger ?? (logger = ImageLoader.LoggerFactory?.CreateLogger<WmsImageLayer>());
private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger<GroundOverlay>();
public static readonly DependencyProperty ServiceUriProperty =
DependencyPropertyHelper.Register<WmsImageLayer, Uri>(nameof(ServiceUri), null,
@ -112,10 +112,9 @@ namespace MapControl
{
try
{
using (var stream = await ImageLoader.HttpClient.GetStreamAsync(uri))
{
element = XDocument.Load(stream).Root;
}
using var stream = await ImageLoader.HttpClient.GetStreamAsync(uri);
element = XDocument.Load(stream).Root;
}
catch (Exception ex)
{

View file

@ -31,10 +31,9 @@ namespace MapControl
if (capabilitiesUri.IsAbsoluteUri && (capabilitiesUri.Scheme == "http" || capabilitiesUri.Scheme == "https"))
{
using (var stream = await ImageLoader.HttpClient.GetStreamAsync(capabilitiesUri))
{
capabilities = ReadCapabilities(XDocument.Load(stream).Root, layer, capabilitiesUri.ToString());
}
using var stream = await ImageLoader.HttpClient.GetStreamAsync(capabilitiesUri);
capabilities = ReadCapabilities(XDocument.Load(stream).Root, layer, capabilitiesUri.ToString());
}
else
{
@ -46,12 +45,8 @@ namespace MapControl
public static WmtsCapabilities ReadCapabilities(XElement capabilitiesElement, string layer, string capabilitiesUrl)
{
var contentsElement = capabilitiesElement.Element(wmts + "Contents");
if (contentsElement == null)
{
throw new ArgumentException("Contents element not found.");
}
var contentsElement = capabilitiesElement.Element(wmts + "Contents")
?? throw new ArgumentException("Contents element not found.");
XElement layerElement;
@ -102,12 +97,8 @@ namespace MapControl
{
var tileMatrixSetElement = contentsElement
.Elements(wmts + "TileMatrixSet")
.FirstOrDefault(s => s.Element(ows + "Identifier")?.Value == tileMatrixSetId);
if (tileMatrixSetElement == null)
{
throw new ArgumentException($"Linked TileMatrixSet element not found in Layer \"{layer}\".");
}
.FirstOrDefault(s => s.Element(ows + "Identifier")?.Value == tileMatrixSetId)
?? throw new ArgumentException($"Linked TileMatrixSet element not found in Layer \"{layer}\".");
tileMatrixSets.Add(ReadTileMatrixSet(tileMatrixSetElement));
}
@ -134,7 +125,7 @@ namespace MapControl
.ToLookup(r => r.Attribute("format").Value,
r => r.Attribute("template").Value);
if (resourceUrls.Any())
if (resourceUrls.Count != 0)
{
var urlTemplates = resourceUrls.Contains(formatPng) ? resourceUrls[formatPng]
: resourceUrls.Contains(formatJpg) ? resourceUrls[formatJpg]

View file

@ -23,7 +23,7 @@ namespace MapControl
public class WmtsTileLayer : MapTileLayerBase
{
private static ILogger logger;
private static ILogger Logger => logger ?? (logger = ImageLoader.LoggerFactory?.CreateLogger<WmtsTileLayer>());
private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger<GroundOverlay>();
public static readonly DependencyProperty CapabilitiesUriProperty =
DependencyPropertyHelper.Register<WmtsTileLayer, Uri>(nameof(CapabilitiesUri), null,

View file

@ -6,7 +6,7 @@ namespace MapControl
{
public WmtsTileMatrixSet TileMatrixSet { get; set; }
public override Uri GetUri(int column, int row, int zoomLevel)
public override Uri GetUri(int zoomLevel, int column, int row)
{
Uri uri = null;

View file

@ -1,320 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9545F73C-9C35-4CF6-BAAE-19A0BAEBD344}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MapControl</RootNamespace>
<AssemblyName>MapControl.UWP</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.26100.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<GenerateLibraryLayout>true</GenerateLibraryLayout>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Shared\AutoEquirectangularProjection.cs">
<Link>AutoEquirectangularProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\AzimuthalEquidistantProjection.cs">
<Link>AzimuthalEquidistantProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\AzimuthalProjection.cs">
<Link>AzimuthalProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\BoundingBox.cs">
<Link>BoundingBox.cs</Link>
</Compile>
<Compile Include="..\Shared\BoundingBoxTileSource.cs">
<Link>BoundingBoxTileSource.cs</Link>
</Compile>
<Compile Include="..\Shared\CenteredBoundingBox.cs">
<Link>CenteredBoundingBox.cs</Link>
</Compile>
<Compile Include="..\Shared\DispatcherTimerExtensions.cs">
<Link>DispatcherTimerExtensions.cs</Link>
</Compile>
<Compile Include="..\Shared\EquirectangularProjection.cs">
<Link>EquirectangularProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\Etrs89UtmProjection.cs">
<Link>Etrs89UtmProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\FilePath.cs">
<Link>FilePath.cs</Link>
</Compile>
<Compile Include="..\Shared\GeoImage.cs">
<Link>GeoImage.cs</Link>
</Compile>
<Compile Include="..\Shared\GnomonicProjection.cs">
<Link>GnomonicProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\GroundOverlay.cs">
<Link>GroundOverlay.cs</Link>
</Compile>
<Compile Include="..\Shared\ImageFileCache.cs">
<Link>ImageFileCache.cs</Link>
</Compile>
<Compile Include="..\Shared\ImageLoader.cs">
<Link>ImageLoader.cs</Link>
</Compile>
<Compile Include="..\Shared\LatLonBox.cs">
<Link>LatLonBox.cs</Link>
</Compile>
<Compile Include="..\Shared\Location.cs">
<Link>Location.cs</Link>
</Compile>
<Compile Include="..\Shared\LocationCollection.cs">
<Link>LocationCollection.cs</Link>
</Compile>
<Compile Include="..\Shared\Map.cs">
<Link>Map.cs</Link>
</Compile>
<Compile Include="..\Shared\MapBase.cs">
<Link>MapBase.cs</Link>
</Compile>
<Compile Include="..\Shared\MapBase.MapLayer.cs">
<Link>MapBase.MapLayer.cs</Link>
</Compile>
<Compile Include="..\Shared\MapBorderPanel.cs">
<Link>MapBorderPanel.cs</Link>
</Compile>
<Compile Include="..\Shared\MapGraticule.cs">
<Link>MapGraticule.cs</Link>
</Compile>
<Compile Include="..\Shared\MapImageLayer.cs">
<Link>MapImageLayer.cs</Link>
</Compile>
<Compile Include="..\Shared\MapItem.cs">
<Link>MapItem.cs</Link>
</Compile>
<Compile Include="..\Shared\MapItemsControl.cs">
<Link>MapItemsControl.cs</Link>
</Compile>
<Compile Include="..\Shared\MapMultiPolygon.cs">
<Link>MapMultiPolygon.cs</Link>
</Compile>
<Compile Include="..\Shared\MapPanel.cs">
<Link>MapPanel.cs</Link>
</Compile>
<Compile Include="..\Shared\MapPath.cs">
<Link>MapPath.cs</Link>
</Compile>
<Compile Include="..\Shared\MapPolygon.cs">
<Link>MapPolygon.cs</Link>
</Compile>
<Compile Include="..\Shared\MapPolyline.cs">
<Link>MapPolyline.cs</Link>
</Compile>
<Compile Include="..\Shared\MapProjection.cs">
<Link>MapProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\MapProjectionFactory.cs">
<Link>MapProjectionFactory.cs</Link>
</Compile>
<Compile Include="..\Shared\MapScale.cs">
<Link>MapScale.cs</Link>
</Compile>
<Compile Include="..\Shared\MapTileLayer.cs">
<Link>MapTileLayer.cs</Link>
</Compile>
<Compile Include="..\Shared\MapTileLayerBase.cs">
<Link>MapTileLayerBase.cs</Link>
</Compile>
<Compile Include="..\Shared\Nad27UtmProjection.cs">
<Link>Nad27UtmProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\Nad83UtmProjection.cs">
<Link>Nad83UtmProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\OrthographicProjection.cs">
<Link>OrthographicProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\PolarStereographicProjection.cs">
<Link>PolarStereographicProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\PolygonCollection.cs">
<Link>PolygonCollection.cs</Link>
</Compile>
<Compile Include="..\Shared\PushpinBorder.cs">
<Link>PushpinBorder.cs</Link>
</Compile>
<Compile Include="..\Shared\StereographicProjection.cs">
<Link>StereographicProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\Tile.cs">
<Link>Tile.cs</Link>
</Compile>
<Compile Include="..\Shared\TileCollection.cs">
<Link>TileCollection.cs</Link>
</Compile>
<Compile Include="..\Shared\TileImageLoader.cs">
<Link>TileImageLoader.cs</Link>
</Compile>
<Compile Include="..\Shared\TileMatrix.cs">
<Link>TileMatrix.cs</Link>
</Compile>
<Compile Include="..\Shared\TileSource.cs">
<Link>TileSource.cs</Link>
</Compile>
<Compile Include="..\Shared\TransverseMercatorProjection.cs">
<Link>TransverseMercatorProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\TypeConverters.cs">
<Link>TypeConverters.cs</Link>
</Compile>
<Compile Include="..\Shared\ViewportChangedEventArgs.cs">
<Link>ViewportChangedEventArgs.cs</Link>
</Compile>
<Compile Include="..\Shared\ViewTransform.cs">
<Link>ViewTransform.cs</Link>
</Compile>
<Compile Include="..\Shared\WebMercatorProjection.cs">
<Link>WebMercatorProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\Wgs84UtmProjection.cs">
<Link>Wgs84UtmProjection.cs</Link>
</Compile>
<Compile Include="..\Shared\WmsImageLayer.cs">
<Link>WmsImageLayer.cs</Link>
</Compile>
<Compile Include="..\Shared\WmtsCapabilities.cs">
<Link>WmtsCapabilities.cs</Link>
</Compile>
<Compile Include="..\Shared\WmtsTileLayer.cs">
<Link>WmtsTileLayer.cs</Link>
</Compile>
<Compile Include="..\Shared\WmtsTileMatrix.cs">
<Link>WmtsTileMatrix.cs</Link>
</Compile>
<Compile Include="..\Shared\WmtsTileMatrixLayer.cs">
<Link>WmtsTileMatrixLayer.cs</Link>
</Compile>
<Compile Include="..\Shared\WmtsTileMatrixSet.cs">
<Link>WmtsTileMatrixSet.cs</Link>
</Compile>
<Compile Include="..\Shared\WmtsTileSource.cs">
<Link>WmtsTileSource.cs</Link>
</Compile>
<Compile Include="..\Shared\WorldMercatorProjection.cs">
<Link>WorldMercatorProjection.cs</Link>
</Compile>
<Compile Include="..\WinUI\DependencyPropertyHelper.WinUI.cs">
<Link>DependencyPropertyHelper.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\GeoImage.WinUI.cs">
<Link>GeoImage.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\ImageLoader.WinUI.cs">
<Link>ImageLoader.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\Map.WinUI.cs">
<Link>Map.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapBase.WinUI.cs">
<Link>MapBase.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapContentControl.WinUI.cs">
<Link>MapContentControl.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapGraticule.WinUI.cs">
<Link>MapGraticule.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapImageLayer.WinUI.cs">
<Link>MapImageLayer.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapItem.WinUI.cs">
<Link>MapItem.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapItemsControl.WinUI.cs">
<Link>MapItemsControl.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapPanel.WinUI.cs">
<Link>MapPanel.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapPath.WinUI.cs">
<Link>MapPath.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\MapPolypoint.WinUI.cs">
<Link>MapPolypoint.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\Matrix.WinUI.cs">
<Link>Matrix.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\Point.WinUI.cs">
<Link>Point.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\PushpinBorder.WinUI.cs">
<Link>PushpinBorder.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\Rect.WinUI.cs">
<Link>Rect.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\Tile.WinUI.cs">
<Link>Tile.WinUI.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Properties\MapControl.UWP.rd.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions">
<Version>9.0.8</Version>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.Memory">
<Version>9.0.8</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.14</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Include="..\..\MapControl.snk">
<Link>MapControl.snk</Link>
</None>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Page Include="Themes\Generic.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>..\..\MapControl.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<UseUwp>true</UseUwp>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DisableRuntimeMarshalling>true</DisableRuntimeMarshalling>
<DefaultLanguage>en-US</DefaultLanguage>
<DefineConstants>UWP</DefineConstants>
<RootNamespace>MapControl</RootNamespace>
<AssemblyTitle>XAML Map Control Library for UWP</AssemblyTitle>
<GeneratePackageOnBuild>$(GeneratePackage)</GeneratePackageOnBuild>
<PackageId>XAML.MapControl.UWP</PackageId>
<Title>$(AssemblyTitle)</Title>
<Description>A set of UWP controls for rendering raster maps from different providers like OpenStreetMap and various types of map overlays</Description>
</PropertyGroup>
<ItemGroup>
<Folder Include="Themes\" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Shared\*.cs" />
<Compile Include="..\WinUI\*.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.9" />
</ItemGroup>
</Project>

View file

@ -1,13 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("XAML Map Control Library for UWP")]
[assembly: AssemblyProduct("XAML Map Control")]
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © 2024 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("13.0.0")]
[assembly: AssemblyFileVersion("13.0.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="MapControl.UWP">
</Library>
</Directives>

View file

@ -34,10 +34,9 @@ namespace MapControl
if (File.Exists(path))
{
using (var stream = File.OpenRead(path))
{
image = LoadImage(stream);
}
using var stream = File.OpenRead(path);
image = LoadImage(stream);
}
return image;

View file

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0-windows;net462</TargetFrameworks>
<LangVersion Condition="'$(TargetFramework)'=='net462'">8.0</LangVersion>
<UseWPF>true</UseWPF>
<DefineConstants>WPF</DefineConstants>
<RootNamespace>MapControl</RootNamespace>
@ -25,7 +26,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.9" />
</ItemGroup>
</Project>

View file

@ -54,29 +54,27 @@ namespace MapControl
protected void UpdateData(IEnumerable<Location> locations, bool closed)
{
using (var context = ((StreamGeometry)Data).Open())
{
if (ParentMap != null && locations != null)
{
var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault());
using var context = ((StreamGeometry)Data).Open();
AddPolylinePoints(context, locations, longitudeOffset, closed);
}
if (ParentMap != null && locations != null)
{
var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault());
AddPolylinePoints(context, locations, longitudeOffset, closed);
}
}
protected void UpdateData(IEnumerable<IEnumerable<Location>> polygons)
{
using (var context = ((StreamGeometry)Data).Open())
{
if (ParentMap != null && polygons != null)
{
var longitudeOffset = GetLongitudeOffset(Location);
using var context = ((StreamGeometry)Data).Open();
foreach (var locations in polygons)
{
AddPolylinePoints(context, locations, longitudeOffset, true);
}
if (ParentMap != null && polygons != null)
{
var longitudeOffset = GetLongitudeOffset(Location);
foreach (var locations in polygons)
{
AddPolylinePoints(context, locations, longitudeOffset, true);
}
}
}

View file

@ -20,52 +20,51 @@ namespace MapControl
var file = await StorageFile.GetFileFromPathAsync(FilePath.GetFullPath(sourcePath));
using (var stream = await file.OpenReadAsync())
using var stream = await file.OpenReadAsync();
var decoder = await BitmapDecoder.CreateAsync(stream);
bitmap = await ImageLoader.LoadWriteableBitmapAsync(decoder);
var geoKeyDirectoryQuery = QueryString(GeoKeyDirectoryTag);
var pixelScaleQuery = QueryString(ModelPixelScaleTag);
var tiePointQuery = QueryString(ModelTiePointTag);
var transformationQuery = QueryString(ModelTransformationTag);
var metadata = await decoder.BitmapProperties.GetPropertiesAsync(
new string[]
{
pixelScaleQuery,
tiePointQuery,
transformationQuery,
geoKeyDirectoryQuery
});
if (metadata.TryGetValue(pixelScaleQuery, out BitmapTypedValue pixelScaleValue) &&
pixelScaleValue.Value is double[] pixelScale &&
pixelScale.Length == 3 &&
metadata.TryGetValue(tiePointQuery, out BitmapTypedValue tiePointValue) &&
tiePointValue.Value is double[] tiePoint &&
tiePoint.Length >= 6)
{
var decoder = await BitmapDecoder.CreateAsync(stream);
transform = new Matrix(pixelScale[0], 0d, 0d, -pixelScale[1], tiePoint[3], tiePoint[4]);
}
else if (metadata.TryGetValue(transformationQuery, out BitmapTypedValue transformValue) &&
transformValue.Value is double[] transformValues &&
transformValues.Length == 16)
{
transform = new Matrix(transformValues[0], transformValues[1],
transformValues[4], transformValues[5],
transformValues[3], transformValues[7]);
}
else
{
throw new ArgumentException("No coordinate transformation found.");
}
bitmap = await ImageLoader.LoadWriteableBitmapAsync(decoder);
var geoKeyDirectoryQuery = QueryString(GeoKeyDirectoryTag);
var pixelScaleQuery = QueryString(ModelPixelScaleTag);
var tiePointQuery = QueryString(ModelTiePointTag);
var transformationQuery = QueryString(ModelTransformationTag);
var metadata = await decoder.BitmapProperties.GetPropertiesAsync(
new string[]
{
pixelScaleQuery,
tiePointQuery,
transformationQuery,
geoKeyDirectoryQuery
});
if (metadata.TryGetValue(pixelScaleQuery, out BitmapTypedValue pixelScaleValue) &&
pixelScaleValue.Value is double[] pixelScale &&
pixelScale.Length == 3 &&
metadata.TryGetValue(tiePointQuery, out BitmapTypedValue tiePointValue) &&
tiePointValue.Value is double[] tiePoint &&
tiePoint.Length >= 6)
{
transform = new Matrix(pixelScale[0], 0d, 0d, -pixelScale[1], tiePoint[3], tiePoint[4]);
}
else if (metadata.TryGetValue(transformationQuery, out BitmapTypedValue transformValue) &&
transformValue.Value is double[] transformValues &&
transformValues.Length == 16)
{
transform = new Matrix(transformValues[0], transformValues[1],
transformValues[4], transformValues[5],
transformValues[3], transformValues[7]);
}
else
{
throw new ArgumentException("No coordinate transformation found.");
}
if (metadata.TryGetValue(geoKeyDirectoryQuery, out BitmapTypedValue geoKeyDirValue) &&
geoKeyDirValue.Value is short[] geoKeyDirectory)
{
projection = GetProjection(geoKeyDirectory);
}
if (metadata.TryGetValue(geoKeyDirectoryQuery, out BitmapTypedValue geoKeyDirValue) &&
geoKeyDirValue.Value is short[] geoKeyDirectory)
{
projection = GetProjection(geoKeyDirectory);
}
return new GeoBitmap(bitmap, transform, projection);

View file

@ -34,10 +34,9 @@ namespace MapControl
public static async Task<ImageSource> LoadImageAsync(Stream stream)
{
using (var randomAccessStream = stream.AsRandomAccessStream())
{
return await LoadImageAsync(randomAccessStream);
}
using var randomAccessStream = stream.AsRandomAccessStream();
return await LoadImageAsync(randomAccessStream);
}
public static async Task<ImageSource> LoadImageAsync(string path)
@ -50,10 +49,9 @@ namespace MapControl
{
var file = await StorageFile.GetFileFromPathAsync(path);
using (var randomAccessStream = await file.OpenReadAsync())
{
image = await LoadImageAsync(randomAccessStream);
}
using var randomAccessStream = await file.OpenReadAsync();
image = await LoadImageAsync(randomAccessStream);
}
return image;
@ -84,13 +82,12 @@ namespace MapControl
if (buffer != null)
{
using (var memoryStream = new MemoryStream(buffer))
using (var randomAccessStream = memoryStream.AsRandomAccessStream())
{
var decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
using var memoryStream = new MemoryStream(buffer);
using var randomAccessStream = memoryStream.AsRandomAccessStream();
bitmap = await LoadWriteableBitmapAsync(decoder);
}
var decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
bitmap = await LoadWriteableBitmapAsync(decoder);
}
}
catch (Exception ex)

View file

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.17763.0</TargetFramework>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<TargetFramework>net9.0-windows10.0.17763.0</TargetFramework>
<UseWinUI>true</UseWinUI>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>WINUI</DefineConstants>
<RootNamespace>MapControl</RootNamespace>
<AssemblyTitle>XAML Map Control Library for WinUI</AssemblyTitle>
@ -17,9 +17,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250606001" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.250907003" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4948" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.9" />
</ItemGroup>
</Project>