mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2026-04-05 06:26:41 +00:00
Version 4.1.
This commit is contained in:
parent
ef6d1ed959
commit
467d82ead7
25 changed files with 323 additions and 309 deletions
|
|
@ -76,18 +76,6 @@ namespace MapControl
|
|||
private double centerLongitude;
|
||||
private bool internalPropertyChange;
|
||||
|
||||
public MapBase()
|
||||
{
|
||||
Initialize();
|
||||
|
||||
MapProjection = new WebMercatorProjection();
|
||||
ScaleRotateTransform.Children.Add(ScaleTransform);
|
||||
ScaleRotateTransform.Children.Add(RotateTransform);
|
||||
}
|
||||
|
||||
partial void Initialize(); // Windows Runtime and Silverlight only
|
||||
partial void RemoveAnimation(DependencyProperty property); // WPF only
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the current viewport has changed.
|
||||
/// </summary>
|
||||
|
|
@ -504,7 +492,8 @@ namespace MapControl
|
|||
targetCenter.Latitude,
|
||||
Location.NearestLongitude(targetCenter.Longitude, Center.Longitude))),
|
||||
Duration = AnimationDuration,
|
||||
EasingFunction = AnimationEasingFunction
|
||||
EasingFunction = AnimationEasingFunction,
|
||||
FillBehavior = AnimationFillBehavior
|
||||
};
|
||||
|
||||
centerAnimation.Completed += CenterAnimationCompleted;
|
||||
|
|
@ -522,7 +511,6 @@ namespace MapControl
|
|||
|
||||
InternalSetValue(CenterProperty, TargetCenter);
|
||||
InternalSetValue(CenterPointProperty, MapProjection.LocationToPoint(TargetCenter));
|
||||
RemoveAnimation(CenterPointProperty); // remove holding animation in WPF
|
||||
UpdateTransform();
|
||||
}
|
||||
}
|
||||
|
|
@ -607,7 +595,8 @@ namespace MapControl
|
|||
{
|
||||
To = targetZoomLevel,
|
||||
Duration = AnimationDuration,
|
||||
EasingFunction = AnimationEasingFunction
|
||||
EasingFunction = AnimationEasingFunction,
|
||||
FillBehavior = AnimationFillBehavior
|
||||
};
|
||||
|
||||
zoomLevelAnimation.Completed += ZoomLevelAnimationCompleted;
|
||||
|
|
@ -624,8 +613,6 @@ namespace MapControl
|
|||
zoomLevelAnimation = null;
|
||||
|
||||
InternalSetValue(ZoomLevelProperty, TargetZoomLevel);
|
||||
RemoveAnimation(ZoomLevelProperty); // remove holding animation in WPF
|
||||
|
||||
UpdateTransform(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -681,7 +668,8 @@ namespace MapControl
|
|||
{
|
||||
By = delta,
|
||||
Duration = AnimationDuration,
|
||||
EasingFunction = AnimationEasingFunction
|
||||
EasingFunction = AnimationEasingFunction,
|
||||
FillBehavior = AnimationFillBehavior
|
||||
};
|
||||
|
||||
headingAnimation.Completed += HeadingAnimationCompleted;
|
||||
|
|
@ -698,7 +686,6 @@ namespace MapControl
|
|||
headingAnimation = null;
|
||||
|
||||
InternalSetValue(HeadingProperty, TargetHeading);
|
||||
RemoveAnimation(HeadingProperty); // remove holding animation in WPF
|
||||
UpdateTransform();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
50
MapControl/Shared/MapItemsControl.cs
Normal file
50
MapControl/Shared/MapItemsControl.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2017 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINDOWS_UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Container class for an item in a MapItemsControl.
|
||||
/// </summary>
|
||||
public class MapItem : ListBoxItem
|
||||
{
|
||||
public MapItem()
|
||||
{
|
||||
DefaultStyleKey = typeof(MapItem);
|
||||
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages a collection of selectable items on a Map.
|
||||
/// </summary>
|
||||
public class MapItemsControl : ListBox
|
||||
{
|
||||
public MapItemsControl()
|
||||
{
|
||||
DefaultStyleKey = typeof(MapItemsControl);
|
||||
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
protected override DependencyObject GetContainerForItemOverride()
|
||||
{
|
||||
return new MapItem();
|
||||
}
|
||||
|
||||
protected override bool IsItemItsOwnContainerOverride(object item)
|
||||
{
|
||||
return item is MapItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,10 @@ using System.Windows.Media;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Optional interface to hold the value of the MapPanel.ParentMap attached property.
|
||||
/// May be used to get notified when the property value changes.
|
||||
/// </summary>
|
||||
public interface IMapElement
|
||||
{
|
||||
MapBase ParentMap { get; set; }
|
||||
|
|
@ -35,6 +39,13 @@ namespace MapControl
|
|||
public static readonly DependencyProperty BoundingBoxProperty = DependencyProperty.RegisterAttached(
|
||||
"BoundingBox", typeof(BoundingBox), typeof(MapPanel), new PropertyMetadata(null, BoundingBoxPropertyChanged));
|
||||
|
||||
private MapBase parentMap;
|
||||
|
||||
public MapPanel()
|
||||
{
|
||||
InitMapElement(this);
|
||||
}
|
||||
|
||||
public static Location GetLocation(UIElement element)
|
||||
{
|
||||
return (Location)element.GetValue(LocationProperty);
|
||||
|
|
@ -55,12 +66,10 @@ namespace MapControl
|
|||
element.SetValue(BoundingBoxProperty, value);
|
||||
}
|
||||
|
||||
private MapBase parentMap;
|
||||
|
||||
public MapBase ParentMap
|
||||
{
|
||||
get { return parentMap; }
|
||||
set { SetParentMapOverride(value); }
|
||||
set { SetParentMap(value); }
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
|
|
@ -101,7 +110,7 @@ namespace MapControl
|
|||
return finalSize;
|
||||
}
|
||||
|
||||
protected virtual void SetParentMapOverride(MapBase map)
|
||||
protected virtual void SetParentMap(MapBase map)
|
||||
{
|
||||
if (parentMap != null && parentMap != this)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ namespace MapControl
|
|||
nameof(Location), typeof(Location), typeof(MapPath),
|
||||
new PropertyMetadata(null, (o, e) => ((MapPath)o).LocationPropertyChanged()));
|
||||
|
||||
public MapPath()
|
||||
{
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
public Location Location
|
||||
{
|
||||
get { return (Location)GetValue(LocationProperty); }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#if WINDOWS_UWP
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
|
|
@ -21,13 +22,13 @@ namespace MapControl
|
|||
{
|
||||
public interface ITileImageLoader
|
||||
{
|
||||
void LoadTiles(MapTileLayer tileLayer);
|
||||
Task LoadTilesAsync(MapTileLayer tileLayer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the map viewport with map tiles from a TileSource.
|
||||
/// </summary>
|
||||
public partial class MapTileLayer : Panel, IMapLayer
|
||||
public class MapTileLayer : Panel, IMapLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// A default MapTileLayer using OpenStreetMap data.
|
||||
|
|
@ -66,9 +67,6 @@ namespace MapControl
|
|||
public static readonly DependencyProperty MaxZoomLevelProperty = DependencyProperty.Register(
|
||||
nameof(MaxZoomLevel), typeof(int), typeof(MapTileLayer), new PropertyMetadata(18));
|
||||
|
||||
public static readonly DependencyProperty MaxParallelDownloadsProperty = DependencyProperty.Register(
|
||||
nameof(MaxParallelDownloads), typeof(int), typeof(MapTileLayer), new PropertyMetadata(4));
|
||||
|
||||
public static readonly DependencyProperty UpdateIntervalProperty = DependencyProperty.Register(
|
||||
nameof(UpdateInterval), typeof(TimeSpan), typeof(MapTileLayer),
|
||||
new PropertyMetadata(TimeSpan.FromSeconds(0.2), (o, e) => ((MapTileLayer)o).updateTimer.Interval = (TimeSpan)e.NewValue));
|
||||
|
|
@ -92,17 +90,16 @@ namespace MapControl
|
|||
|
||||
public MapTileLayer(ITileImageLoader tileImageLoader)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
IsHitTestVisible = false;
|
||||
RenderTransform = new MatrixTransform();
|
||||
TileImageLoader = tileImageLoader;
|
||||
Tiles = new List<Tile>();
|
||||
|
||||
updateTimer = new DispatcherTimer { Interval = UpdateInterval };
|
||||
updateTimer.Tick += (s, e) => UpdateTileGrid();
|
||||
}
|
||||
|
||||
partial void Initialize(); // Windows Runtime and Silverlight only
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
public ITileImageLoader TileImageLoader { get; private set; }
|
||||
public ICollection<Tile> Tiles { get; private set; }
|
||||
|
|
@ -162,15 +159,6 @@ namespace MapControl
|
|||
set { SetValue(MaxZoomLevelProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of parallel downloads that may be performed by the MapTileLayer's ITileImageLoader.
|
||||
/// </summary>
|
||||
public int MaxParallelDownloads
|
||||
{
|
||||
get { return (int)GetValue(MaxParallelDownloadsProperty); }
|
||||
set { SetValue(MaxParallelDownloadsProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time interval between tile updates.
|
||||
/// </summary>
|
||||
|
|
@ -400,7 +388,7 @@ namespace MapControl
|
|||
Children.Add(tile.Image);
|
||||
}
|
||||
|
||||
TileImageLoader.LoadTiles(this);
|
||||
var task = TileImageLoader.LoadTilesAsync(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
MapControl/Shared/Pushpin.cs
Normal file
25
MapControl/Shared/Pushpin.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2017 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINDOWS_UWP
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows.Controls;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Pushpin at a geographic location specified by the MapPanel.Location attached property.
|
||||
/// </summary>
|
||||
public class Pushpin : ContentControl
|
||||
{
|
||||
public Pushpin()
|
||||
{
|
||||
DefaultStyleKey = typeof(Pushpin);
|
||||
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ using System.Collections.Concurrent;
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
#if WINDOWS_UWP
|
||||
|
|
@ -22,11 +23,6 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public partial class TileImageLoader : ITileImageLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// The HttpClient instance used when image data is downloaded from a web resource.
|
||||
/// </summary>
|
||||
public static HttpClient HttpClient { get; set; } = new HttpClient();
|
||||
|
||||
/// <summary>
|
||||
/// Default expiration time for cached tile images. Used when no expiration time
|
||||
/// was transmitted on download. The default value is one day.
|
||||
|
|
@ -50,13 +46,10 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public static string CacheKeyFormat { get; set; } = "{0};{1};{2};{3}{4}";
|
||||
|
||||
private const string bingMapsTileInfo = "X-VE-Tile-Info";
|
||||
private const string bingMapsNoTile = "no-tile";
|
||||
|
||||
private readonly ConcurrentStack<Tile> pendingTiles = new ConcurrentStack<Tile>();
|
||||
private int taskCount;
|
||||
|
||||
public void LoadTiles(MapTileLayer tileLayer)
|
||||
public async Task LoadTilesAsync(MapTileLayer tileLayer)
|
||||
{
|
||||
pendingTiles.Clear();
|
||||
|
||||
|
|
@ -69,18 +62,18 @@ namespace MapControl
|
|||
if (Cache == null || string.IsNullOrEmpty(sourceName) ||
|
||||
tileSource.UriFormat == null || !tileSource.UriFormat.StartsWith("http"))
|
||||
{
|
||||
// no caching, load tile images in UI thread
|
||||
// no caching, load tile images directly
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
LoadTileImage(tileSource, tile);
|
||||
await LoadTileImageAsync(tileSource, tile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pendingTiles.PushRange(tiles.Reverse().ToArray());
|
||||
|
||||
while (taskCount < Math.Min(pendingTiles.Count, tileLayer.MaxParallelDownloads))
|
||||
while (taskCount < Math.Min(pendingTiles.Count, ServicePointManager.DefaultConnectionLimit))
|
||||
{
|
||||
Interlocked.Increment(ref taskCount);
|
||||
|
||||
|
|
@ -95,13 +88,13 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private void LoadTileImage(TileSource tileSource, Tile tile)
|
||||
private async Task LoadTileImageAsync(TileSource tileSource, Tile tile)
|
||||
{
|
||||
tile.Pending = false;
|
||||
|
||||
try
|
||||
{
|
||||
var imageSource = tileSource.LoadImage(tile.XIndex, tile.Y, tile.ZoomLevel);
|
||||
var imageSource = await tileSource.LoadImageAsync(tile.XIndex, tile.Y, tile.ZoomLevel);
|
||||
|
||||
if (imageSource != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,13 +4,6 @@
|
|||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
#if WINDOWS_UWP
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
|
|
@ -92,17 +85,6 @@ namespace MapControl
|
|||
return getUri?.Invoke(x, y, zoomLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the map tile ImageSource without caching in TileImageLoader.Cache.
|
||||
/// By overriding LoadImage an application can provide arbitrary tile images.
|
||||
/// </summary>
|
||||
public virtual ImageSource LoadImage(int x, int y, int zoomLevel)
|
||||
{
|
||||
var uri = GetUri(x, y, zoomLevel);
|
||||
|
||||
return uri != null ? new BitmapImage(uri) : null;
|
||||
}
|
||||
|
||||
private Uri GetBasicUri(int x, int y, int zoomLevel)
|
||||
{
|
||||
return new Uri(uriFormat
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue