mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2026-04-04 14:08:32 +00:00
Version 4.1.
This commit is contained in:
parent
ef6d1ed959
commit
467d82ead7
25 changed files with 323 additions and 309 deletions
|
|
@ -6,11 +6,14 @@ using Windows.Foundation;
|
|||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapBase
|
||||
{
|
||||
private const FillBehavior AnimationFillBehavior = FillBehavior.HoldEnd;
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
|
||||
nameof(Foreground), typeof(Brush), typeof(MapBase),
|
||||
new PropertyMetadata(new SolidColorBrush(Colors.Black)));
|
||||
|
|
@ -39,25 +42,24 @@ namespace MapControl
|
|||
nameof(TargetHeading), typeof(double), typeof(MapBase),
|
||||
new PropertyMetadata(0d, (o, e) => ((MapBase)o).TargetHeadingPropertyChanged((double)e.NewValue)));
|
||||
|
||||
partial void Initialize()
|
||||
public MapBase()
|
||||
{
|
||||
MapProjection = new WebMercatorProjection();
|
||||
ScaleRotateTransform.Children.Add(ScaleTransform);
|
||||
ScaleRotateTransform.Children.Add(RotateTransform);
|
||||
|
||||
// set Background by Style to enable resetting by ClearValue in MapLayerPropertyChanged
|
||||
var style = new Style(typeof(MapBase));
|
||||
style.Setters.Add(new Setter(BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
|
||||
Style = style;
|
||||
|
||||
var clip = new RectangleGeometry();
|
||||
Clip = clip;
|
||||
Clip = new RectangleGeometry();
|
||||
|
||||
SizeChanged += (s, e) =>
|
||||
{
|
||||
if (clip.Rect.Width != e.NewSize.Width || clip.Rect.Height != e.NewSize.Height)
|
||||
{
|
||||
clip.Rect = new Rect(0d, 0d, e.NewSize.Width, e.NewSize.Height);
|
||||
|
||||
ResetTransformCenter();
|
||||
UpdateTransform();
|
||||
}
|
||||
Clip.Rect = new Rect(0d, 0d, e.NewSize.Width, e.NewSize.Height);
|
||||
ResetTransformCenter();
|
||||
UpdateTransform();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<GenerateLibraryLayout>true</GenerateLibraryLayout>
|
||||
<NoWarn>CS1998</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
|
@ -88,6 +89,9 @@
|
|||
<Compile Include="..\Shared\MapImageLayer.cs">
|
||||
<Link>MapImageLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapItemsControl.cs">
|
||||
<Link>MapItemsControl.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapOverlay.cs">
|
||||
<Link>MapOverlay.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -112,6 +116,9 @@
|
|||
<Compile Include="..\Shared\OrthographicProjection.cs">
|
||||
<Link>OrthographicProjection.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\Pushpin.cs">
|
||||
<Link>Pushpin.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\StereographicProjection.cs">
|
||||
<Link>StereographicProjection.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -143,18 +150,15 @@
|
|||
<Compile Include="MapBase.UWP.cs" />
|
||||
<Compile Include="MapGraticule.UWP.cs" />
|
||||
<Compile Include="MapImageLayer.UWP.cs" />
|
||||
<Compile Include="MapItem.UWP.cs" />
|
||||
<Compile Include="MapItemsControl.UWP.cs" />
|
||||
<Compile Include="MapOverlay.UWP.cs" />
|
||||
<Compile Include="MapPanel.UWP.cs" />
|
||||
<Compile Include="MapPath.UWP.cs" />
|
||||
<Compile Include="MapPolyline.UWP.cs" />
|
||||
<Compile Include="MapTileLayer.UWP.cs" />
|
||||
<Compile Include="MatrixEx.UWP.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Pushpin.UWP.cs" />
|
||||
<Compile Include="Tile.UWP.cs" />
|
||||
<Compile Include="TileImageLoader.UWP.cs" />
|
||||
<Compile Include="TileSource.UWP.cs" />
|
||||
<EmbeddedResource Include="Properties\MapControl.UWP.rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2017 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Container class for an item in a MapItemsControl.
|
||||
/// </summary>
|
||||
public class MapItem : ListBoxItem
|
||||
{
|
||||
public MapItem()
|
||||
{
|
||||
DefaultStyleKey = typeof(MapItem);
|
||||
MapPanel.AddParentMapHandlers(this);
|
||||
}
|
||||
|
||||
public Location Location
|
||||
{
|
||||
get { return (Location)GetValue(MapPanel.LocationProperty); }
|
||||
set { SetValue(MapPanel.LocationProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2017 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages a collection of selectable items on a Map. Uses MapItem as item container class.
|
||||
/// </summary>
|
||||
public class MapItemsControl : ListBox
|
||||
{
|
||||
public MapItemsControl()
|
||||
{
|
||||
DefaultStyleKey = typeof(MapItemsControl);
|
||||
MapPanel.AddParentMapHandlers(this);
|
||||
}
|
||||
|
||||
protected override DependencyObject GetContainerForItemOverride()
|
||||
{
|
||||
return new MapItem();
|
||||
}
|
||||
|
||||
protected override bool IsItemItsOwnContainerOverride(object item)
|
||||
{
|
||||
return item is MapItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ namespace MapControl
|
|||
public static readonly DependencyProperty StrokeMiterLimitProperty = DependencyProperty.Register(
|
||||
nameof(StrokeMiterLimit), typeof(double), typeof(MapOverlay), new PropertyMetadata(1d));
|
||||
|
||||
protected override void SetParentMapOverride(MapBase parentMap)
|
||||
protected override void SetParentMap(MapBase parentMap)
|
||||
{
|
||||
if (GetBindingExpression(ForegroundProperty) != null)
|
||||
{
|
||||
|
|
@ -89,7 +89,7 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
base.SetParentMapOverride(parentMap);
|
||||
base.SetParentMap(parentMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,27 +12,20 @@ namespace MapControl
|
|||
public static readonly DependencyProperty ParentMapProperty = DependencyProperty.RegisterAttached(
|
||||
"ParentMap", typeof(MapBase), typeof(MapPanel), new PropertyMetadata(null, ParentMapPropertyChanged));
|
||||
|
||||
public MapPanel()
|
||||
public static void InitMapElement(FrameworkElement element)
|
||||
{
|
||||
if (this is MapBase)
|
||||
if (element is MapBase)
|
||||
{
|
||||
SetValue(ParentMapProperty, this);
|
||||
element.SetValue(ParentMapProperty, element);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddParentMapHandlers(this);
|
||||
}
|
||||
}
|
||||
// Workaround for missing property value inheritance in Windows Runtime.
|
||||
// Loaded and Unloaded handlers set and clear the ParentMap property value.
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to work around missing property value inheritance in Silverlight and Windows Runtime.
|
||||
/// Adds Loaded and Unloaded event handlers to the specified FrameworkElement, which set and clear the
|
||||
/// value of the MapPanel.ParentMap attached property.
|
||||
/// </summary>
|
||||
public static void AddParentMapHandlers(FrameworkElement element)
|
||||
{
|
||||
element.Loaded += (s, e) => GetParentMap(element);
|
||||
element.Unloaded += (s, e) => element.ClearValue(ParentMapProperty);
|
||||
element.Loaded += (s, e) => GetParentMap(element);
|
||||
element.Unloaded += (s, e) => element.ClearValue(ParentMapProperty);
|
||||
}
|
||||
}
|
||||
|
||||
public static MapBase GetParentMap(UIElement element)
|
||||
|
|
@ -49,20 +42,12 @@ namespace MapControl
|
|||
|
||||
private static MapBase FindParentMap(UIElement element)
|
||||
{
|
||||
MapBase parentMap = null;
|
||||
var parentElement = VisualTreeHelper.GetParent(element) as UIElement;
|
||||
var parent = VisualTreeHelper.GetParent(element) as UIElement;
|
||||
|
||||
if (parentElement != null)
|
||||
{
|
||||
parentMap = parentElement as MapBase;
|
||||
|
||||
if (parentMap == null)
|
||||
{
|
||||
parentMap = GetParentMap(parentElement);
|
||||
}
|
||||
}
|
||||
|
||||
return parentMap;
|
||||
return parent == null ? null
|
||||
: ((parent as MapBase)
|
||||
?? (MapBase)element.GetValue(ParentMapProperty)
|
||||
?? FindParentMap(parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,6 @@ namespace MapControl
|
|||
{
|
||||
private Geometry data;
|
||||
|
||||
public MapPath()
|
||||
{
|
||||
MapPanel.AddParentMapHandlers(this);
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
if (Stretch != Stretch.None)
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2017 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays a pushpin at a geographic location provided by the MapPanel.Location attached property.
|
||||
/// </summary>
|
||||
public class Pushpin : ContentControl
|
||||
{
|
||||
public Pushpin()
|
||||
{
|
||||
DefaultStyleKey = typeof(Pushpin);
|
||||
MapPanel.AddParentMapHandlers(this);
|
||||
}
|
||||
|
||||
public Location Location
|
||||
{
|
||||
get { return (Location)GetValue(MapPanel.LocationProperty); }
|
||||
set { SetValue(MapPanel.LocationProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ using Windows.Storage;
|
|||
using Windows.Storage.Streams;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
using Windows.Web.Http;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
|
|
@ -31,11 +30,6 @@ namespace MapControl
|
|||
var buffer = cacheItem?.Buffer;
|
||||
var loaded = false;
|
||||
|
||||
//if (buffer != null)
|
||||
//{
|
||||
// Debug.WriteLine("TileImageLoader: {0}: expire{1} {2}", cacheKey, cacheItem.Expiration < DateTime.UtcNow ? "d" : "s", cacheItem.Expiration);
|
||||
//}
|
||||
|
||||
if (buffer == null || cacheItem.Expiration < DateTime.UtcNow)
|
||||
{
|
||||
loaded = await DownloadTileImageAsync(tile, uri, cacheKey);
|
||||
|
|
@ -49,28 +43,26 @@ namespace MapControl
|
|||
|
||||
private async Task<bool> DownloadTileImageAsync(Tile tile, Uri uri, string cacheKey)
|
||||
{
|
||||
var success = false;
|
||||
|
||||
try
|
||||
{
|
||||
using (var response = await HttpClient.GetAsync(uri))
|
||||
using (var response = await TileSource.HttpClient.GetAsync(uri))
|
||||
{
|
||||
if (response.IsSuccessStatusCode)
|
||||
success = response.IsSuccessStatusCode;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
string tileInfo;
|
||||
|
||||
if (!response.Headers.TryGetValue(bingMapsTileInfo, out tileInfo) ||
|
||||
tileInfo != bingMapsNoTile)
|
||||
{
|
||||
var buffer = await response.Content.ReadAsBufferAsync();
|
||||
|
||||
await SetTileImageAsync(tile, buffer); // create BitmapImage in UI thread before caching
|
||||
|
||||
await Cache.SetAsync(cacheKey, buffer, GetExpiration(response));
|
||||
}
|
||||
|
||||
return true;
|
||||
Debug.WriteLine("TileImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
|
||||
}
|
||||
else if (TileSource.TileAvailable(response.Headers))
|
||||
{
|
||||
var buffer = await response.Content.ReadAsBufferAsync();
|
||||
|
||||
Debug.WriteLine("TileImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
|
||||
await SetTileImageAsync(tile, buffer); // create BitmapImage before caching
|
||||
|
||||
await Cache.SetAsync(cacheKey, buffer, GetExpiration(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -78,7 +70,7 @@ namespace MapControl
|
|||
Debug.WriteLine("TileImageLoader: {0}: {1}", uri, ex.Message);
|
||||
}
|
||||
|
||||
return false;
|
||||
return success;
|
||||
}
|
||||
|
||||
private async Task SetTileImageAsync(Tile tile, IBuffer buffer)
|
||||
|
|
|
|||
84
MapControl/UWP/TileSource.UWP.cs
Normal file
84
MapControl/UWP/TileSource.UWP.cs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2017 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
using Windows.Web.Http;
|
||||
using Windows.Web.Http.Headers;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class TileSource
|
||||
{
|
||||
/// <summary>
|
||||
/// The HttpClient instance used when image data is downloaded from a web resource.
|
||||
/// </summary>
|
||||
public static HttpClient HttpClient { get; set; } = new HttpClient();
|
||||
|
||||
/// <summary>
|
||||
/// Check HTTP response headers for tile unavailability, e.g. X-VE-Tile-Info=no-tile
|
||||
/// </summary>
|
||||
public static bool TileAvailable(HttpResponseHeaderCollection responseHeaders)
|
||||
{
|
||||
string tileInfo;
|
||||
|
||||
return !responseHeaders.TryGetValue("X-VE-Tile-Info", out tileInfo) || tileInfo != "no-tile";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load a tile ImageSource asynchronously from GetUri(x, y, zoomLevel)
|
||||
/// </summary>
|
||||
public virtual async Task<ImageSource> LoadImageAsync(int x, int y, int zoomLevel)
|
||||
{
|
||||
ImageSource imageSource = null;
|
||||
|
||||
var uri = GetUri(x, y, zoomLevel);
|
||||
|
||||
if (uri != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (uri.Scheme == "http")
|
||||
{
|
||||
using (var response = await HttpClient.GetAsync(uri))
|
||||
{
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Debug.WriteLine("TileSource: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
|
||||
}
|
||||
else if (TileAvailable(response.Headers))
|
||||
{
|
||||
var bitmapImage = new BitmapImage();
|
||||
|
||||
using (var stream = new InMemoryRandomAccessStream())
|
||||
{
|
||||
await response.Content.WriteToStreamAsync(stream);
|
||||
stream.Seek(0);
|
||||
|
||||
await bitmapImage.SetSourceAsync(stream);
|
||||
}
|
||||
|
||||
imageSource = bitmapImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
imageSource = new BitmapImage(uri);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("TileSource: {0}: {1}", uri, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return imageSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue