mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 2.3.0:
- Added BingMapsTileLayer - Added TileLayer.DescriptionInlines property - Added global Settings class - Added Phone Silverlight 8.1 build target - Use expiration time of downloaded images for caching
This commit is contained in:
parent
8917e1d4cb
commit
91ff46c506
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
|
|
@ -128,12 +128,18 @@ namespace Caching
|
||||||
|
|
||||||
if (path != null)
|
if (path != null)
|
||||||
{
|
{
|
||||||
var creationTime = File.GetLastWriteTimeUtc(path).ToBinary();
|
var expirationTime = File.GetLastAccessTimeUtc(path);
|
||||||
|
var creationTime = File.GetLastWriteTimeUtc(path);
|
||||||
|
|
||||||
|
if (expirationTime < creationTime)
|
||||||
|
{
|
||||||
|
expirationTime = creationTime;
|
||||||
|
}
|
||||||
|
|
||||||
using (var fileStream = new FileStream(path, FileMode.Open))
|
using (var fileStream = new FileStream(path, FileMode.Open))
|
||||||
using (var memoryStream = new MemoryStream((int)(fileStream.Length + 8)))
|
using (var memoryStream = new MemoryStream((int)(fileStream.Length + 8)))
|
||||||
{
|
{
|
||||||
memoryStream.Write(BitConverter.GetBytes(creationTime), 0, 8);
|
memoryStream.Write(BitConverter.GetBytes(expirationTime.ToBinary()), 0, 8);
|
||||||
fileStream.CopyTo(memoryStream);
|
fileStream.CopyTo(memoryStream);
|
||||||
value = memoryStream.GetBuffer();
|
value = memoryStream.GetBuffer();
|
||||||
}
|
}
|
||||||
|
|
@ -150,6 +156,7 @@ namespace Caching
|
||||||
public override CacheItem GetCacheItem(string key, string regionName = null)
|
public override CacheItem GetCacheItem(string key, string regionName = null)
|
||||||
{
|
{
|
||||||
var value = Get(key, regionName);
|
var value = Get(key, regionName);
|
||||||
|
|
||||||
return value != null ? new CacheItem(key, value) : null;
|
return value != null ? new CacheItem(key, value) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,6 +204,9 @@ namespace Caching
|
||||||
fileStream.Write(buffer, 8, buffer.Length - 8);
|
fileStream.Write(buffer, 8, buffer.Length - 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expirationTime = DateTime.FromBinary(BitConverter.ToInt64(buffer, 0));
|
||||||
|
File.SetLastAccessTimeUtc(path, expirationTime);
|
||||||
|
|
||||||
var fileSecurity = File.GetAccessControl(path);
|
var fileSecurity = File.GetAccessControl(path);
|
||||||
fileSecurity.AddAccessRule(fullControlRule);
|
fileSecurity.AddAccessRule(fullControlRule);
|
||||||
File.SetAccessControl(path, fileSecurity);
|
File.SetAccessControl(path, fileSecurity);
|
||||||
|
|
@ -220,14 +230,18 @@ namespace Caching
|
||||||
public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
|
public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
|
||||||
{
|
{
|
||||||
var oldValue = Get(key, regionName);
|
var oldValue = Get(key, regionName);
|
||||||
|
|
||||||
Set(key, value, policy);
|
Set(key, value, policy);
|
||||||
|
|
||||||
return oldValue;
|
return oldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CacheItem AddOrGetExisting(CacheItem item, CacheItemPolicy policy)
|
public override CacheItem AddOrGetExisting(CacheItem item, CacheItemPolicy policy)
|
||||||
{
|
{
|
||||||
var oldItem = GetCacheItem(item.Key, item.RegionName);
|
var oldItem = GetCacheItem(item.Key, item.RegionName);
|
||||||
|
|
||||||
Set(item, policy);
|
Set(item, policy);
|
||||||
|
|
||||||
return oldItem;
|
return oldItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 12.0.30501.0
|
VisualStudioVersion = 12.0.30723.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileDbCache", "Caching\FileDbCache\FileDbCache.csproj", "{EF44F661-B98A-4676-927F-85D138F82300}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileDbCache", "Caching\FileDbCache\FileDbCache.csproj", "{EF44F661-B98A-4676-927F-85D138F82300}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilverlightApplication.Web"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.WPF", "MapControl\MapControl.WPF.csproj", "{226F3575-B683-446D-A2F0-181291DC8787}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.WPF", "MapControl\MapControl.WPF.csproj", "{226F3575-B683-446D-A2F0-181291DC8787}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.Silverlight", "MapControl\MapControl.Silverlight.csproj", "{EB133B78-DEFF-416A-8F0C-89E54D766576}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StoreApplication", "SampleApps\StoreApplication\StoreApplication.csproj", "{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StoreApplication", "SampleApps\StoreApplication\StoreApplication.csproj", "{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.WinRT", "MapControl\WinRT\MapControl.WinRT.csproj", "{63CEFDF7-5170-43B6-86F8-5C4A383A1615}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.WinRT", "MapControl\WinRT\MapControl.WinRT.csproj", "{63CEFDF7-5170-43B6-86F8-5C4A383A1615}"
|
||||||
|
|
@ -23,6 +21,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfApplication", "SampleApp
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneApplication", "SampleApps\PhoneApplication\PhoneApplication.csproj", "{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneApplication", "SampleApps\PhoneApplication\PhoneApplication.csproj", "{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.Silverlight", "MapControl\MapControl.Silverlight.csproj", "{EB133B78-DEFF-416A-8F0C-89E54D766576}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.PhoneSilverlight", "MapControl\MapControl.PhoneSilverlight.csproj", "{3499D618-2846-4FCE-A418-7D211FDBDCB3}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -49,10 +51,6 @@ Global
|
||||||
{226F3575-B683-446D-A2F0-181291DC8787}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{226F3575-B683-446D-A2F0-181291DC8787}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{226F3575-B683-446D-A2F0-181291DC8787}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{226F3575-B683-446D-A2F0-181291DC8787}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{226F3575-B683-446D-A2F0-181291DC8787}.Release|Any CPU.Build.0 = Release|Any CPU
|
{226F3575-B683-446D-A2F0-181291DC8787}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
{747A3F84-E11F-4EC8-9463-98BBB1E0D0A4}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
|
|
@ -73,6 +71,14 @@ Global
|
||||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.Build.0 = Release|Any CPU
|
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EB133B78-DEFF-416A-8F0C-89E54D766576}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3499D618-2846-4FCE-A418-7D211FDBDCB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3499D618-2846-4FCE-A418-7D211FDBDCB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3499D618-2846-4FCE-A418-7D211FDBDCB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3499D618-2846-4FCE-A418-7D211FDBDCB3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
||||||
153
MapControl/BingMapsTileLayer.cs
Normal file
153
MapControl/BingMapsTileLayer.cs
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||||
|
// Copyright © 2014 Clemens Fischer
|
||||||
|
// Licensed under the Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Net;
|
||||||
|
using System.Xml;
|
||||||
|
#if WINDOWS_RUNTIME
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
#else
|
||||||
|
using System.Windows;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
public class BingMapsTileLayer : TileLayer
|
||||||
|
{
|
||||||
|
public enum MapMode
|
||||||
|
{
|
||||||
|
Road, Aerial, AerialWithLabels
|
||||||
|
}
|
||||||
|
|
||||||
|
public BingMapsTileLayer()
|
||||||
|
{
|
||||||
|
MinZoomLevel = 1;
|
||||||
|
MaxZoomLevel = 21;
|
||||||
|
Loaded += OnLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ApiKey { get; set; }
|
||||||
|
|
||||||
|
public MapMode Mode { get; set; }
|
||||||
|
public string Culture { get; set; }
|
||||||
|
|
||||||
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Loaded -= OnLoaded;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(ApiKey))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("A Bing Maps API Key must be assigned to the ApiKey property.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var uri = string.Format("http://dev.virtualearth.net/REST/V1/Imagery/Metadata/{0}?output=xml&key={1}", Mode, ApiKey);
|
||||||
|
var request = HttpWebRequest.CreateHttp(uri);
|
||||||
|
|
||||||
|
request.BeginGetResponse(HandleImageryMetadataResponse, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleImageryMetadataResponse(IAsyncResult asyncResult)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = (HttpWebRequest)asyncResult.AsyncState;
|
||||||
|
|
||||||
|
using (var response = request.EndGetResponse(asyncResult))
|
||||||
|
using (var responseStream = response.GetResponseStream())
|
||||||
|
using (var xmlReader = XmlReader.Create(responseStream))
|
||||||
|
{
|
||||||
|
ReadImageryMetadataResponse(xmlReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadImageryMetadataResponse(XmlReader xmlReader)
|
||||||
|
{
|
||||||
|
string imageUrl = null;
|
||||||
|
string[] imageUrlSubdomains = null;
|
||||||
|
int? zoomMin = null;
|
||||||
|
int? zoomMax = null;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.Element)
|
||||||
|
{
|
||||||
|
switch (xmlReader.Name)
|
||||||
|
{
|
||||||
|
case "ImageUrl":
|
||||||
|
imageUrl = xmlReader.ReadElementContentAsString();
|
||||||
|
break;
|
||||||
|
case "ImageUrlSubdomains":
|
||||||
|
imageUrlSubdomains = ReadStrings(xmlReader.ReadSubtree());
|
||||||
|
break;
|
||||||
|
case "ZoomMin":
|
||||||
|
zoomMin = xmlReader.ReadElementContentAsInt();
|
||||||
|
break;
|
||||||
|
case "ZoomMax":
|
||||||
|
zoomMax = xmlReader.ReadElementContentAsInt();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
xmlReader.Read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xmlReader.Read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (xmlReader.NodeType != XmlNodeType.None);
|
||||||
|
|
||||||
|
if (imageUrl != null && imageUrlSubdomains != null && imageUrlSubdomains.Length > 0)
|
||||||
|
{
|
||||||
|
Dispatcher.BeginInvoke(new Action(() =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Culture))
|
||||||
|
{
|
||||||
|
Culture = CultureInfo.CurrentUICulture.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileSource = new BingMapsTileSource(imageUrl.Replace("{culture}", Culture), imageUrlSubdomains);
|
||||||
|
|
||||||
|
if (zoomMin.HasValue && zoomMin.Value > MinZoomLevel)
|
||||||
|
{
|
||||||
|
MinZoomLevel = zoomMin.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zoomMax.HasValue && zoomMax.Value < MaxZoomLevel)
|
||||||
|
{
|
||||||
|
MaxZoomLevel = zoomMax.Value;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string[] ReadStrings(XmlReader xmlReader)
|
||||||
|
{
|
||||||
|
var strings = new List<string>();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "string")
|
||||||
|
{
|
||||||
|
strings.Add(xmlReader.ReadElementContentAsString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xmlReader.Read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (xmlReader.NodeType != XmlNodeType.None);
|
||||||
|
|
||||||
|
return strings.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
MapControl/BingMapsTileSource.cs
Normal file
39
MapControl/BingMapsTileSource.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||||
|
// Copyright © 2014 Clemens Fischer
|
||||||
|
// Licensed under the Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
internal class BingMapsTileSource : TileSource
|
||||||
|
{
|
||||||
|
private string[] subdomains;
|
||||||
|
|
||||||
|
public BingMapsTileSource(string uriFormat, string[] subdomains)
|
||||||
|
: base(uriFormat)
|
||||||
|
{
|
||||||
|
this.subdomains = subdomains;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Uri GetUri(int x, int y, int zoomLevel)
|
||||||
|
{
|
||||||
|
if (zoomLevel < 1)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var subdomain = subdomains[(x + y) % subdomains.Length];
|
||||||
|
var quadkey = new char[zoomLevel];
|
||||||
|
|
||||||
|
for (var z = zoomLevel - 1; z >= 0; z--, x /= 2, y /= 2)
|
||||||
|
{
|
||||||
|
quadkey[z] = (char)('0' + 2 * (y % 2) + (x % 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Uri(UriFormat.
|
||||||
|
Replace("{subdomain}", subdomain).
|
||||||
|
Replace("{quadkey}", new string(quadkey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,10 +13,6 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
internal static partial class Extensions
|
internal static partial class Extensions
|
||||||
{
|
{
|
||||||
public static void Freeze(this object freezable)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Matrix Translate(this Matrix matrix, double offsetX, double offsetY)
|
public static Matrix Translate(this Matrix matrix, double offsetX, double offsetY)
|
||||||
{
|
{
|
||||||
matrix.OffsetX += offsetX;
|
matrix.OffsetX += offsetX;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
// Copyright © 2014 Clemens Fischer
|
// Copyright © 2014 Clemens Fischer
|
||||||
// Licensed under the Microsoft Public License (Ms-PL)
|
// Licensed under the Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
using System;
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
|
using Windows.UI.Core;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
using Windows.UI.Xaml.Media.Animation;
|
using Windows.UI.Xaml.Media.Animation;
|
||||||
|
|
@ -11,6 +13,11 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
internal static partial class Extensions
|
internal static partial class Extensions
|
||||||
{
|
{
|
||||||
|
public static void BeginInvoke(this CoreDispatcher dispatcher, Action action)
|
||||||
|
{
|
||||||
|
var asyncAction = dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(action));
|
||||||
|
}
|
||||||
|
|
||||||
public static Point Transform(this GeneralTransform transform, Point point)
|
public static Point Transform(this GeneralTransform transform, Point point)
|
||||||
{
|
{
|
||||||
return transform.TransformPoint(point);
|
return transform.TransformPoint(point);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace MapControl
|
||||||
|
|
||||||
if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
|
if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
|
||||||
{
|
{
|
||||||
throw new ArgumentException(string.Format("{0}: no GlyphTypeface found", typeface.FontFamily));
|
throw new ArgumentException(string.Format("{0}: No GlyphTypeface found", typeface.FontFamily));
|
||||||
}
|
}
|
||||||
|
|
||||||
var glyphIndices = new ushort[text.Length];
|
var glyphIndices = new ushort[text.Length];
|
||||||
|
|
|
||||||
60
MapControl/HyperlinkText.cs
Normal file
60
MapControl/HyperlinkText.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||||
|
// Copyright © 2014 Clemens Fischer
|
||||||
|
// Licensed under the Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
#if WINDOWS_RUNTIME
|
||||||
|
using Windows.UI.Xaml.Documents;
|
||||||
|
#else
|
||||||
|
using System.Windows.Documents;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
public static class HyperlinkText
|
||||||
|
{
|
||||||
|
private static Regex regex = new Regex(@"\[([^\]]+)\]\(([^\)]+)\)");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts text containing hyperlinks in markdown syntax [text](url)
|
||||||
|
/// to a collection of Run and Hyperlink inlines.
|
||||||
|
/// </summary>
|
||||||
|
public static ICollection<Inline> ToInlines(this string text)
|
||||||
|
{
|
||||||
|
var inlines = new List<Inline>();
|
||||||
|
|
||||||
|
while (!string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
var match = regex.Match(text);
|
||||||
|
Uri uri;
|
||||||
|
|
||||||
|
if (match.Success &&
|
||||||
|
match.Groups.Count == 3 &&
|
||||||
|
Uri.TryCreate(match.Groups[2].Value, UriKind.Absolute, out uri))
|
||||||
|
{
|
||||||
|
inlines.Add(new Run { Text = text.Substring(0, match.Index) });
|
||||||
|
text = text.Substring(match.Index + match.Length);
|
||||||
|
|
||||||
|
var link = new Hyperlink { NavigateUri = uri };
|
||||||
|
link.Inlines.Add(new Run { Text = match.Groups[1].Value });
|
||||||
|
#if SILVERLIGHT
|
||||||
|
link.TargetName = "_blank";
|
||||||
|
#elif !WINDOWS_RUNTIME
|
||||||
|
link.ToolTip = uri.ToString();
|
||||||
|
link.RequestNavigate += (s, e) => System.Diagnostics.Process.Start(e.Uri.ToString());
|
||||||
|
#endif
|
||||||
|
inlines.Add(link);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inlines.Add(new Run { Text = text });
|
||||||
|
text = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inlines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace MapControl
|
namespace MapControl
|
||||||
{
|
{
|
||||||
public struct Int32Rect
|
internal struct Int32Rect
|
||||||
{
|
{
|
||||||
public Int32Rect(int x, int y, int width, int height)
|
public Int32Rect(int x, int y, int width, int height)
|
||||||
: this()
|
: this()
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,6 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
private const double MaximumZoomLevel = 22d;
|
private const double MaximumZoomLevel = 22d;
|
||||||
|
|
||||||
public static TimeSpan AnimationDuration = TimeSpan.FromSeconds(0.5);
|
|
||||||
public static EasingFunctionBase AnimationEasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut };
|
|
||||||
|
|
||||||
public static readonly DependencyProperty TileLayersProperty = DependencyProperty.Register(
|
public static readonly DependencyProperty TileLayersProperty = DependencyProperty.Register(
|
||||||
"TileLayers", typeof(TileLayerCollection), typeof(MapBase), new PropertyMetadata(null,
|
"TileLayers", typeof(TileLayerCollection), typeof(MapBase), new PropertyMetadata(null,
|
||||||
(o, e) => ((MapBase)o).TileLayersPropertyChanged((TileLayerCollection)e.OldValue, (TileLayerCollection)e.NewValue)));
|
(o, e) => ((MapBase)o).TileLayersPropertyChanged((TileLayerCollection)e.OldValue, (TileLayerCollection)e.NewValue)));
|
||||||
|
|
@ -74,7 +71,7 @@ namespace MapControl
|
||||||
SetParentMap();
|
SetParentMap();
|
||||||
|
|
||||||
TileLayers = new TileLayerCollection();
|
TileLayers = new TileLayerCollection();
|
||||||
InternalChildren.Add(tileContainer);
|
Children.Add(tileContainer);
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
Loaded += OnLoaded;
|
Loaded += OnLoaded;
|
||||||
|
|
@ -578,8 +575,8 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
From = MapTransform.Transform(Center),
|
From = MapTransform.Transform(Center),
|
||||||
To = MapTransform.Transform(targetCenter, Center.Longitude),
|
To = MapTransform.Transform(targetCenter, Center.Longitude),
|
||||||
Duration = AnimationDuration,
|
Duration = Settings.MapAnimationDuration,
|
||||||
EasingFunction = AnimationEasingFunction,
|
EasingFunction = Settings.MapAnimationEasingFunction,
|
||||||
FillBehavior = FillBehavior.HoldEnd
|
FillBehavior = FillBehavior.HoldEnd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -683,8 +680,8 @@ namespace MapControl
|
||||||
zoomLevelAnimation = new DoubleAnimation
|
zoomLevelAnimation = new DoubleAnimation
|
||||||
{
|
{
|
||||||
To = targetZoomLevel,
|
To = targetZoomLevel,
|
||||||
Duration = AnimationDuration,
|
Duration = Settings.MapAnimationDuration,
|
||||||
EasingFunction = AnimationEasingFunction,
|
EasingFunction = Settings.MapAnimationEasingFunction,
|
||||||
FillBehavior = FillBehavior.HoldEnd
|
FillBehavior = FillBehavior.HoldEnd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -758,8 +755,8 @@ namespace MapControl
|
||||||
headingAnimation = new DoubleAnimation
|
headingAnimation = new DoubleAnimation
|
||||||
{
|
{
|
||||||
By = delta,
|
By = delta,
|
||||||
Duration = AnimationDuration,
|
Duration = Settings.MapAnimationDuration,
|
||||||
EasingFunction = AnimationEasingFunction,
|
EasingFunction = Settings.MapAnimationEasingFunction,
|
||||||
FillBehavior = FillBehavior.HoldEnd
|
FillBehavior = FillBehavior.HoldEnd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
150
MapControl/MapControl.PhoneSilverlight.csproj
Normal file
150
MapControl/MapControl.PhoneSilverlight.csproj
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>10.0.20506</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{3499D618-2846-4FCE-A418-7D211FDBDCB3}</ProjectGuid>
|
||||||
|
<ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>MapControl</RootNamespace>
|
||||||
|
<AssemblyName>MapControl.PhoneSilverlight</AssemblyName>
|
||||||
|
<TargetFrameworkIdentifier>WindowsPhone</TargetFrameworkIdentifier>
|
||||||
|
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
|
||||||
|
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
|
||||||
|
<SilverlightApplication>false</SilverlightApplication>
|
||||||
|
<ValidateXaml>true</ValidateXaml>
|
||||||
|
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||||
|
<ThrowErrorsInValidation>true</ThrowErrorsInValidation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>Bin\Debug</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>Bin\Release</OutputPath>
|
||||||
|
<DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>Bin\x86\Debug</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>Bin\x86\Release</OutputPath>
|
||||||
|
<DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>Bin\ARM\Debug</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>Bin\ARM\Release</OutputPath>
|
||||||
|
<DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="BingMapsTileLayer.cs" />
|
||||||
|
<Compile Include="BingMapsTileSource.cs" />
|
||||||
|
<Compile Include="Extensions.Silverlight.cs" />
|
||||||
|
<Compile Include="Extensions.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="HyperlinkText.cs" />
|
||||||
|
<Compile Include="ImageTileSource.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="IMapElement.cs" />
|
||||||
|
<Compile Include="Int32Rect.cs" />
|
||||||
|
<Compile Include="Location.cs" />
|
||||||
|
<Compile Include="LocationCollection.cs" />
|
||||||
|
<Compile Include="LocationCollectionConverter.cs" />
|
||||||
|
<Compile Include="LocationConverter.cs" />
|
||||||
|
<Compile Include="Map.Silverlight.cs" />
|
||||||
|
<Compile Include="MapBase.cs" />
|
||||||
|
<Compile Include="MapBase.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapGraticule.cs" />
|
||||||
|
<Compile Include="MapGraticule.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapImage.cs" />
|
||||||
|
<Compile Include="MapImageLayer.cs" />
|
||||||
|
<Compile Include="MapImageLayer.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapItem.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapItemsControl.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapOverlay.cs" />
|
||||||
|
<Compile Include="MapOverlay.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapPanel.cs" />
|
||||||
|
<Compile Include="MapPanel.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapPath.cs" />
|
||||||
|
<Compile Include="MapPath.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapPolyline.cs" />
|
||||||
|
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapRectangle.cs" />
|
||||||
|
<Compile Include="MapRectangle.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="MapTransform.cs" />
|
||||||
|
<Compile Include="MercatorTransform.cs" />
|
||||||
|
<Compile Include="PanelBase.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Pushpin.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="Settings.cs" />
|
||||||
|
<Compile Include="Tile.cs" />
|
||||||
|
<Compile Include="Tile.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="TileContainer.cs" />
|
||||||
|
<Compile Include="TileContainer.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="TileImageLoader.Silverlight.cs" />
|
||||||
|
<Compile Include="TileLayer.cs" />
|
||||||
|
<Compile Include="TileLayerCollection.cs" />
|
||||||
|
<Compile Include="TileSource.cs" />
|
||||||
|
<Compile Include="TileSourceConverter.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Include="Themes\Generic.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
|
||||||
|
<ProjectExtensions />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
15
MapControl/MapControl.PhoneSilverlight.csproj.user
Normal file
15
MapControl/MapControl.PhoneSilverlight.csproj.user
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<FlavorProperties GUID="{C089C8C0-30E0-4E22-80C0-CE093F111A43}">
|
||||||
|
<SilverlightMobileCSProjectFlavor>
|
||||||
|
<FullDeploy>True</FullDeploy>
|
||||||
|
<DebuggerType>Managed</DebuggerType>
|
||||||
|
<DebuggerAgentType>Managed</DebuggerAgentType>
|
||||||
|
<Tombstone>False</Tombstone>
|
||||||
|
</SilverlightMobileCSProjectFlavor>
|
||||||
|
</FlavorProperties>
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
</Project>
|
||||||
|
|
@ -65,10 +65,14 @@
|
||||||
<HintPath>$(TargetFrameworkDirectory)System.Core.dll</HintPath>
|
<HintPath>$(TargetFrameworkDirectory)System.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Net" />
|
<Reference Include="System.Net" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="BingMapsTileLayer.cs" />
|
||||||
|
<Compile Include="BingMapsTileSource.cs" />
|
||||||
<Compile Include="Extensions.Silverlight.cs" />
|
<Compile Include="Extensions.Silverlight.cs" />
|
||||||
<Compile Include="Extensions.Silverlight.WinRT.cs" />
|
<Compile Include="Extensions.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="HyperlinkText.cs" />
|
||||||
<Compile Include="ImageTileSource.Silverlight.WinRT.cs">
|
<Compile Include="ImageTileSource.Silverlight.WinRT.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -97,11 +101,13 @@
|
||||||
<Compile Include="MapPolyline.cs" />
|
<Compile Include="MapPolyline.cs" />
|
||||||
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
|
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
|
||||||
<Compile Include="MapRectangle.cs" />
|
<Compile Include="MapRectangle.cs" />
|
||||||
|
<Compile Include="MapRectangle.Silverlight.WinRT.cs" />
|
||||||
<Compile Include="MapTransform.cs" />
|
<Compile Include="MapTransform.cs" />
|
||||||
<Compile Include="MercatorTransform.cs" />
|
<Compile Include="MercatorTransform.cs" />
|
||||||
<Compile Include="PanelBase.cs" />
|
<Compile Include="PanelBase.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Pushpin.Silverlight.WinRT.cs" />
|
<Compile Include="Pushpin.Silverlight.WinRT.cs" />
|
||||||
|
<Compile Include="Settings.cs" />
|
||||||
<Compile Include="Tile.cs" />
|
<Compile Include="Tile.cs" />
|
||||||
<Compile Include="Tile.Silverlight.WinRT.cs" />
|
<Compile Include="Tile.Silverlight.WinRT.cs" />
|
||||||
<Compile Include="TileContainer.cs" />
|
<Compile Include="TileContainer.cs" />
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,14 @@
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Runtime.Caching" />
|
<Reference Include="System.Runtime.Caching" />
|
||||||
<Reference Include="System.Xaml" />
|
<Reference Include="System.Xaml" />
|
||||||
|
<Reference Include="System.XML" />
|
||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="BingMapsTileLayer.cs" />
|
||||||
|
<Compile Include="BingMapsTileSource.cs" />
|
||||||
<Compile Include="GlyphRunText.cs" />
|
<Compile Include="GlyphRunText.cs" />
|
||||||
|
<Compile Include="HyperlinkText.cs" />
|
||||||
<Compile Include="ImageTileSource.WPF.cs" />
|
<Compile Include="ImageTileSource.WPF.cs" />
|
||||||
<Compile Include="IMapElement.cs" />
|
<Compile Include="IMapElement.cs" />
|
||||||
<Compile Include="Location.cs" />
|
<Compile Include="Location.cs" />
|
||||||
|
|
@ -72,6 +76,7 @@
|
||||||
<Compile Include="MapOverlay.WPF.cs" />
|
<Compile Include="MapOverlay.WPF.cs" />
|
||||||
<Compile Include="MapPanel.cs" />
|
<Compile Include="MapPanel.cs" />
|
||||||
<Compile Include="MapPanel.WPF.cs" />
|
<Compile Include="MapPanel.WPF.cs" />
|
||||||
|
<Compile Include="MapRectangle.WPF.cs" />
|
||||||
<Compile Include="PanelBase.cs" />
|
<Compile Include="PanelBase.cs" />
|
||||||
<Compile Include="MapPath.cs" />
|
<Compile Include="MapPath.cs" />
|
||||||
<Compile Include="MapPath.WPF.cs" />
|
<Compile Include="MapPath.WPF.cs" />
|
||||||
|
|
@ -83,6 +88,7 @@
|
||||||
<Compile Include="MercatorTransform.cs" />
|
<Compile Include="MercatorTransform.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Pushpin.WPF.cs" />
|
<Compile Include="Pushpin.WPF.cs" />
|
||||||
|
<Compile Include="Settings.cs" />
|
||||||
<Compile Include="Tile.cs" />
|
<Compile Include="Tile.cs" />
|
||||||
<Compile Include="Tile.WPF.cs" />
|
<Compile Include="Tile.WPF.cs" />
|
||||||
<Compile Include="TileContainer.cs" />
|
<Compile Include="TileContainer.cs" />
|
||||||
|
|
|
||||||
|
|
@ -29,16 +29,10 @@ namespace MapControl
|
||||||
|
|
||||||
private void SourceChanged(ImageSource image)
|
private void SourceChanged(ImageSource image)
|
||||||
{
|
{
|
||||||
var transform = new MatrixTransform
|
|
||||||
{
|
|
||||||
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
|
|
||||||
};
|
|
||||||
transform.Freeze();
|
|
||||||
|
|
||||||
Fill = new ImageBrush
|
Fill = new ImageBrush
|
||||||
{
|
{
|
||||||
ImageSource = image,
|
ImageSource = image,
|
||||||
RelativeTransform = transform
|
RelativeTransform = FillTransform
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,13 @@ using Windows.UI.Xaml.Media.Imaging;
|
||||||
#else
|
#else
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Threading;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace MapControl
|
namespace MapControl
|
||||||
{
|
{
|
||||||
public partial class MapImageLayer
|
public partial class MapImageLayer
|
||||||
{
|
{
|
||||||
private readonly DispatcherTimer updateTimer = new DispatcherTimer();
|
private void ImageUpdated(BitmapSource bitmap)
|
||||||
|
|
||||||
private void AddDownloadEventHandlers(BitmapSource bitmap)
|
|
||||||
{
|
{
|
||||||
var bitmapImage = bitmap as BitmapImage;
|
var bitmapImage = bitmap as BitmapImage;
|
||||||
|
|
||||||
|
|
@ -35,7 +32,6 @@ namespace MapControl
|
||||||
private void BitmapImageOpened(object sender, RoutedEventArgs e)
|
private void BitmapImageOpened(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var bitmap = (BitmapImage)sender;
|
var bitmap = (BitmapImage)sender;
|
||||||
|
|
||||||
bitmap.ImageOpened -= BitmapImageOpened;
|
bitmap.ImageOpened -= BitmapImageOpened;
|
||||||
bitmap.ImageFailed -= BitmapImageFailed;
|
bitmap.ImageFailed -= BitmapImageFailed;
|
||||||
|
|
||||||
|
|
@ -45,11 +41,12 @@ namespace MapControl
|
||||||
private void BitmapImageFailed(object sender, ExceptionRoutedEventArgs e)
|
private void BitmapImageFailed(object sender, ExceptionRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var bitmap = (BitmapImage)sender;
|
var bitmap = (BitmapImage)sender;
|
||||||
|
|
||||||
bitmap.ImageOpened -= BitmapImageOpened;
|
bitmap.ImageOpened -= BitmapImageOpened;
|
||||||
bitmap.ImageFailed -= BitmapImageFailed;
|
bitmap.ImageFailed -= BitmapImageFailed;
|
||||||
|
|
||||||
((MapImage)Children[currentImageIndex]).Source = null;
|
var mapImage = (MapImage)Children[currentImageIndex];
|
||||||
|
mapImage.Source = null;
|
||||||
|
|
||||||
BlendImages();
|
BlendImages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Threading;
|
|
||||||
|
|
||||||
namespace MapControl
|
namespace MapControl
|
||||||
{
|
{
|
||||||
public partial class MapImageLayer
|
public partial class MapImageLayer
|
||||||
{
|
{
|
||||||
private readonly DispatcherTimer updateTimer = new DispatcherTimer(DispatcherPriority.Background);
|
private void ImageUpdated(BitmapSource bitmap)
|
||||||
|
|
||||||
private void AddDownloadEventHandlers(BitmapSource bitmap)
|
|
||||||
{
|
{
|
||||||
if (bitmap.IsDownloading)
|
if (bitmap != null && !bitmap.IsFrozen && bitmap.IsDownloading)
|
||||||
{
|
{
|
||||||
bitmap.DownloadCompleted += BitmapDownloadCompleted;
|
bitmap.DownloadCompleted += BitmapDownloadCompleted;
|
||||||
bitmap.DownloadFailed += BitmapDownloadFailed;
|
bitmap.DownloadFailed += BitmapDownloadFailed;
|
||||||
|
|
@ -29,7 +26,6 @@ namespace MapControl
|
||||||
private void BitmapDownloadCompleted(object sender, EventArgs e)
|
private void BitmapDownloadCompleted(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var bitmap = (BitmapSource)sender;
|
var bitmap = (BitmapSource)sender;
|
||||||
|
|
||||||
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
||||||
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
||||||
|
|
||||||
|
|
@ -39,11 +35,12 @@ namespace MapControl
|
||||||
private void BitmapDownloadFailed(object sender, ExceptionEventArgs e)
|
private void BitmapDownloadFailed(object sender, ExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
var bitmap = (BitmapSource)sender;
|
var bitmap = (BitmapSource)sender;
|
||||||
|
|
||||||
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
||||||
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
||||||
|
|
||||||
((MapImage)Children[currentImageIndex]).Source = null;
|
var mapImage = (MapImage)Children[currentImageIndex];
|
||||||
|
mapImage.Source = null;
|
||||||
|
|
||||||
BlendImages();
|
BlendImages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@ using Windows.UI.Xaml.Media.Animation;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media.Animation;
|
using System.Windows.Media.Animation;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Threading;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace MapControl
|
namespace MapControl
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Map image overlay. Fills the entire viewport with a map image from a web request,
|
/// Map image overlay. Fills the entire viewport with map images provided by a web service,
|
||||||
/// for example from a Web Map Service (WMS).
|
/// e.g. a Web Map Service (WMS). The image request Uri is specified by the UriFormat property.
|
||||||
/// The image request Uri is specified by the UriFormat property.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MapImageLayer : MapPanel
|
public partial class MapImageLayer : MapPanel
|
||||||
{
|
{
|
||||||
|
|
@ -31,6 +31,7 @@ namespace MapControl
|
||||||
public static readonly DependencyProperty RelativeImageSizeProperty = DependencyProperty.Register(
|
public static readonly DependencyProperty RelativeImageSizeProperty = DependencyProperty.Register(
|
||||||
"RelativeImageSize", typeof(double), typeof(MapImageLayer), new PropertyMetadata(1d));
|
"RelativeImageSize", typeof(double), typeof(MapImageLayer), new PropertyMetadata(1d));
|
||||||
|
|
||||||
|
private readonly DispatcherTimer updateTimer;
|
||||||
private int currentImageIndex;
|
private int currentImageIndex;
|
||||||
private bool updateInProgress;
|
private bool updateInProgress;
|
||||||
|
|
||||||
|
|
@ -39,15 +40,15 @@ namespace MapControl
|
||||||
Children.Add(new MapImage { Opacity = 0d });
|
Children.Add(new MapImage { Opacity = 0d });
|
||||||
Children.Add(new MapImage { Opacity = 0d });
|
Children.Add(new MapImage { Opacity = 0d });
|
||||||
|
|
||||||
updateTimer.Interval = TileContainer.UpdateInterval;
|
updateTimer = new DispatcherTimer { Interval = Settings.TileUpdateInterval };
|
||||||
updateTimer.Tick += (s, e) => UpdateImage();
|
updateTimer.Tick += (s, e) => UpdateImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The format string of the image request Uri. The format must contain {X} and {Y}
|
/// The format string of the image request Uri. The format must contain
|
||||||
/// format specifiers for the map width and height in pixels, and either
|
/// {X} and {Y} format specifiers for the map width and height in pixels and either
|
||||||
/// {w},{s},{e},{n} for the bounding box in lat/lon (like for example EPSG:4326) or
|
/// {w},{s},{e},{n} for the bounding box in lat/lon (like EPSG:4326) or
|
||||||
/// {W},{S},{E},{N} for the bounding box in meters (like for example EPSG:3857).
|
/// {W},{S},{E},{N} for the bounding box in meters (like EPSG:3857).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string UriFormat
|
public string UriFormat
|
||||||
{
|
{
|
||||||
|
|
@ -74,10 +75,46 @@ namespace MapControl
|
||||||
updateTimer.Start();
|
updateTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual BitmapSource GetBitmap(double west, double east, double south, double north, int width, int height)
|
protected void UpdateImage()
|
||||||
{
|
{
|
||||||
BitmapImage image = null;
|
updateTimer.Stop();
|
||||||
|
|
||||||
|
if (updateInProgress)
|
||||||
|
{
|
||||||
|
updateTimer.Start(); // update image on next timer tick
|
||||||
|
}
|
||||||
|
else if (ParentMap != null && RenderSize.Width > 0 && RenderSize.Height > 0)
|
||||||
|
{
|
||||||
|
updateInProgress = true;
|
||||||
|
|
||||||
|
var relativeSize = Math.Max(RelativeImageSize, 1d);
|
||||||
|
var width = RenderSize.Width * relativeSize;
|
||||||
|
var height = RenderSize.Height * relativeSize;
|
||||||
|
var dx = (RenderSize.Width - width) / 2d;
|
||||||
|
var dy = (RenderSize.Height - height) / 2d;
|
||||||
|
|
||||||
|
var loc1 = ParentMap.ViewportPointToLocation(new Point(dx, dy));
|
||||||
|
var loc2 = ParentMap.ViewportPointToLocation(new Point(dx + width, dy));
|
||||||
|
var loc3 = ParentMap.ViewportPointToLocation(new Point(dx, dy + height));
|
||||||
|
var loc4 = ParentMap.ViewportPointToLocation(new Point(dx + width, dy + height));
|
||||||
|
|
||||||
|
var west = Math.Min(loc1.Longitude, Math.Min(loc2.Longitude, Math.Min(loc3.Longitude, loc4.Longitude)));
|
||||||
|
var east = Math.Max(loc1.Longitude, Math.Max(loc2.Longitude, Math.Max(loc3.Longitude, loc4.Longitude)));
|
||||||
|
var south = Math.Min(loc1.Latitude, Math.Min(loc2.Latitude, Math.Min(loc3.Latitude, loc4.Latitude)));
|
||||||
|
var north = Math.Max(loc1.Latitude, Math.Max(loc2.Latitude, Math.Max(loc3.Latitude, loc4.Latitude)));
|
||||||
|
|
||||||
|
var p1 = ParentMap.MapTransform.Transform(new Location(south, west));
|
||||||
|
var p2 = ParentMap.MapTransform.Transform(new Location(north, east));
|
||||||
|
|
||||||
|
width = Math.Round((p2.X - p1.X) * ParentMap.ViewportScale);
|
||||||
|
height = Math.Round((p2.Y - p1.Y) * ParentMap.ViewportScale);
|
||||||
|
|
||||||
|
UpdateImage(west, east, south, north, (int)width, (int)height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateImage(double west, double east, double south, double north, int width, int height)
|
||||||
|
{
|
||||||
if (UriFormat != null && width > 0 && height > 0)
|
if (UriFormat != null && width > 0 && height > 0)
|
||||||
{
|
{
|
||||||
var uri = UriFormat.Replace("{X}", width.ToString()).Replace("{Y}", height.ToString());
|
var uri = UriFormat.Replace("{X}", width.ToString()).Replace("{Y}", height.ToString());
|
||||||
|
|
@ -102,98 +139,56 @@ namespace MapControl
|
||||||
Replace("{n}", north.ToString(CultureInfo.InvariantCulture));
|
Replace("{n}", north.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
image = new BitmapImage(new Uri(uri));
|
UpdateImage(west, east, south, north, new Uri(uri));
|
||||||
}
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void UpdateImage()
|
|
||||||
{
|
|
||||||
if (updateInProgress)
|
|
||||||
{
|
|
||||||
updateTimer.Start(); // update image on next timer tick
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
updateTimer.Stop();
|
UpdateImage(west, east, south, north, (BitmapSource)null);
|
||||||
|
|
||||||
if (ParentMap != null && RenderSize.Width > 0 && RenderSize.Height > 0)
|
|
||||||
{
|
|
||||||
updateInProgress = true;
|
|
||||||
|
|
||||||
var relativeSize = Math.Max(RelativeImageSize, 1d);
|
|
||||||
var width = RenderSize.Width * relativeSize;
|
|
||||||
var height = RenderSize.Height * relativeSize;
|
|
||||||
var dx = (RenderSize.Width - width) / 2d;
|
|
||||||
var dy = (RenderSize.Height - height) / 2d;
|
|
||||||
|
|
||||||
var loc1 = ParentMap.ViewportPointToLocation(new Point(dx, dy));
|
|
||||||
var loc2 = ParentMap.ViewportPointToLocation(new Point(dx + width, dy));
|
|
||||||
var loc3 = ParentMap.ViewportPointToLocation(new Point(dx, dy + height));
|
|
||||||
var loc4 = ParentMap.ViewportPointToLocation(new Point(dx + width, dy + height));
|
|
||||||
|
|
||||||
var west = Math.Min(loc1.Longitude, Math.Min(loc2.Longitude, Math.Min(loc3.Longitude, loc4.Longitude)));
|
|
||||||
var east = Math.Max(loc1.Longitude, Math.Max(loc2.Longitude, Math.Max(loc3.Longitude, loc4.Longitude)));
|
|
||||||
var south = Math.Min(loc1.Latitude, Math.Min(loc2.Latitude, Math.Min(loc3.Latitude, loc4.Latitude)));
|
|
||||||
var north = Math.Max(loc1.Latitude, Math.Max(loc2.Latitude, Math.Max(loc3.Latitude, loc4.Latitude)));
|
|
||||||
|
|
||||||
var p1 = ParentMap.MapTransform.Transform(new Location(south, west));
|
|
||||||
var p2 = ParentMap.MapTransform.Transform(new Location(north, east));
|
|
||||||
|
|
||||||
width = Math.Round((p2.X - p1.X) * ParentMap.ViewportScale);
|
|
||||||
height = Math.Round((p2.Y - p1.Y) * ParentMap.ViewportScale);
|
|
||||||
|
|
||||||
var image = GetBitmap(west, east, south, north, (int)width, (int)height);
|
|
||||||
|
|
||||||
UpdateImage(west, east, south, north, image);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateImage(double west, double east, double south, double north, BitmapSource image)
|
protected virtual void UpdateImage(double west, double east, double south, double north, Uri uri)
|
||||||
|
{
|
||||||
|
UpdateImage(west, east, south, north, new BitmapImage(uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateImage(double west, double east, double south, double north, BitmapSource bitmap)
|
||||||
{
|
{
|
||||||
currentImageIndex = (currentImageIndex + 1) % 2;
|
currentImageIndex = (currentImageIndex + 1) % 2;
|
||||||
var mapImage = (MapImage)Children[currentImageIndex];
|
var mapImage = (MapImage)Children[currentImageIndex];
|
||||||
|
|
||||||
mapImage.Source = null;
|
|
||||||
mapImage.North = double.NaN; // avoid frequent MapRectangle.UpdateData() calls
|
mapImage.North = double.NaN; // avoid frequent MapRectangle.UpdateData() calls
|
||||||
mapImage.West = west;
|
mapImage.West = west;
|
||||||
mapImage.East = east;
|
mapImage.East = east;
|
||||||
mapImage.South = south;
|
mapImage.South = south;
|
||||||
mapImage.North = north;
|
mapImage.North = north;
|
||||||
|
mapImage.Source = bitmap;
|
||||||
|
|
||||||
if (image != null)
|
ImageUpdated(bitmap);
|
||||||
{
|
|
||||||
mapImage.Source = image;
|
|
||||||
AddDownloadEventHandlers(image);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BlendImages();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BlendImages()
|
private void BlendImages()
|
||||||
{
|
{
|
||||||
#if WINDOWS_RUNTIME
|
var topImage = (MapImage)Children[currentImageIndex];
|
||||||
var duration = TimeSpan.Zero; // animation not working in Windows Runtime (?)
|
var bottomImage = (MapImage)Children[(currentImageIndex + 1) % 2];
|
||||||
#else
|
|
||||||
var duration = Tile.AnimationDuration;
|
|
||||||
#endif
|
|
||||||
var mapImage = (MapImage)Children[currentImageIndex];
|
|
||||||
var fadeOut = new DoubleAnimation { To = 0d, Duration = duration };
|
|
||||||
|
|
||||||
if (mapImage.Source != null)
|
if (topImage.Source != null)
|
||||||
{
|
{
|
||||||
mapImage.BeginAnimation(UIElement.OpacityProperty,
|
topImage.BeginAnimation(UIElement.OpacityProperty,
|
||||||
new DoubleAnimation { To = 1d, Duration = duration });
|
new DoubleAnimation { To = 1d, Duration = Settings.TileAnimationDuration });
|
||||||
|
|
||||||
fadeOut.BeginTime = duration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapImage = (MapImage)Children[(currentImageIndex + 1) % 2];
|
if (bottomImage.Source != null)
|
||||||
mapImage.BeginAnimation(UIElement.OpacityProperty, fadeOut);
|
{
|
||||||
|
var fadeOutAnimation = new DoubleAnimation { To = 0d, Duration = Settings.TileAnimationDuration };
|
||||||
|
|
||||||
|
if (topImage.Source != null)
|
||||||
|
{
|
||||||
|
fadeOutAnimation.BeginTime = Settings.TileAnimationDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
bottomImage.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
updateInProgress = false;
|
updateInProgress = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ namespace MapControl
|
||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
{
|
{
|
||||||
foreach (UIElement element in InternalChildren)
|
foreach (UIElement element in Children)
|
||||||
{
|
{
|
||||||
var location = GetLocation(element);
|
var location = GetLocation(element);
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@ namespace MapControl
|
||||||
|
|
||||||
protected virtual void OnViewportChanged()
|
protected virtual void OnViewportChanged()
|
||||||
{
|
{
|
||||||
foreach (UIElement element in InternalChildren)
|
foreach (UIElement element in Children)
|
||||||
{
|
{
|
||||||
var location = GetLocation(element);
|
var location = GetLocation(element);
|
||||||
|
|
||||||
|
|
|
||||||
24
MapControl/MapRectangle.Silverlight.WinRT.cs
Normal file
24
MapControl/MapRectangle.Silverlight.WinRT.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||||
|
// Copyright © 2014 Clemens Fischer
|
||||||
|
// Licensed under the Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
#if WINDOWS_RUNTIME
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
#else
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
public partial class MapRectangle
|
||||||
|
{
|
||||||
|
private void SetRect(Rect rect)
|
||||||
|
{
|
||||||
|
((RectangleGeometry)Data).Rect = rect;
|
||||||
|
RenderTransform = ParentMap.ViewportTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
MapControl/MapRectangle.WPF.cs
Normal file
40
MapControl/MapRectangle.WPF.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||||
|
// Copyright © 2014 Clemens Fischer
|
||||||
|
// Licensed under the Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
public partial class MapRectangle
|
||||||
|
{
|
||||||
|
static MapRectangle()
|
||||||
|
{
|
||||||
|
FillTransform.Freeze();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetRect(Rect rect)
|
||||||
|
{
|
||||||
|
// Apply scaling to the RectangleGeometry to compensate for inaccurate hit testing in WPF.
|
||||||
|
// See http://stackoverflow.com/a/19335624/1136211
|
||||||
|
|
||||||
|
var scale = 1e6 / Math.Min(rect.Width, rect.Height);
|
||||||
|
rect.X *= scale;
|
||||||
|
rect.Y *= scale;
|
||||||
|
rect.Width *= scale;
|
||||||
|
rect.Height *= scale;
|
||||||
|
|
||||||
|
var scaleTransform = new ScaleTransform(1d / scale, 1d / scale);
|
||||||
|
scaleTransform.Freeze();
|
||||||
|
|
||||||
|
var transform = new TransformGroup();
|
||||||
|
transform.Children.Add(scaleTransform); // revert scaling
|
||||||
|
transform.Children.Add(ParentMap.ViewportTransform);
|
||||||
|
|
||||||
|
((RectangleGeometry)Data).Rect = rect;
|
||||||
|
RenderTransform = transform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ using Windows.Foundation;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
#else
|
#else
|
||||||
|
using System;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -16,15 +17,15 @@ namespace MapControl
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills a rectangular area defined by South, North, West and East with a Brush.
|
/// Fills a rectangular area defined by South, North, West and East with a Brush.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MapRectangle : MapPath
|
public partial class MapRectangle : MapPath
|
||||||
{
|
{
|
||||||
public static readonly DependencyProperty SouthProperty = DependencyProperty.Register(
|
/// <summary>
|
||||||
"South", typeof(double), typeof(MapRectangle),
|
/// Used in derived classes like MapImage.
|
||||||
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
|
/// </summary>
|
||||||
|
protected static readonly MatrixTransform FillTransform = new MatrixTransform
|
||||||
public static readonly DependencyProperty NorthProperty = DependencyProperty.Register(
|
{
|
||||||
"North", typeof(double), typeof(MapRectangle),
|
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
|
||||||
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
|
};
|
||||||
|
|
||||||
public static readonly DependencyProperty WestProperty = DependencyProperty.Register(
|
public static readonly DependencyProperty WestProperty = DependencyProperty.Register(
|
||||||
"West", typeof(double), typeof(MapRectangle),
|
"West", typeof(double), typeof(MapRectangle),
|
||||||
|
|
@ -34,24 +35,20 @@ namespace MapControl
|
||||||
"East", typeof(double), typeof(MapRectangle),
|
"East", typeof(double), typeof(MapRectangle),
|
||||||
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
|
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty SouthProperty = DependencyProperty.Register(
|
||||||
|
"South", typeof(double), typeof(MapRectangle),
|
||||||
|
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty NorthProperty = DependencyProperty.Register(
|
||||||
|
"North", typeof(double), typeof(MapRectangle),
|
||||||
|
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
|
||||||
|
|
||||||
public MapRectangle()
|
public MapRectangle()
|
||||||
{
|
{
|
||||||
Data = new RectangleGeometry();
|
Data = new RectangleGeometry();
|
||||||
StrokeThickness = 0d;
|
StrokeThickness = 0d;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double South
|
|
||||||
{
|
|
||||||
get { return (double)GetValue(SouthProperty); }
|
|
||||||
set { SetValue(SouthProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public double North
|
|
||||||
{
|
|
||||||
get { return (double)GetValue(NorthProperty); }
|
|
||||||
set { SetValue(NorthProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public double West
|
public double West
|
||||||
{
|
{
|
||||||
get { return (double)GetValue(WestProperty); }
|
get { return (double)GetValue(WestProperty); }
|
||||||
|
|
@ -64,6 +61,18 @@ namespace MapControl
|
||||||
set { SetValue(EastProperty, value); }
|
set { SetValue(EastProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double South
|
||||||
|
{
|
||||||
|
get { return (double)GetValue(SouthProperty); }
|
||||||
|
set { SetValue(SouthProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public double North
|
||||||
|
{
|
||||||
|
get { return (double)GetValue(NorthProperty); }
|
||||||
|
set { SetValue(NorthProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
protected override void UpdateData()
|
protected override void UpdateData()
|
||||||
{
|
{
|
||||||
var geometry = (RectangleGeometry)Data;
|
var geometry = (RectangleGeometry)Data;
|
||||||
|
|
@ -73,25 +82,10 @@ namespace MapControl
|
||||||
!double.IsNaN(West) && !double.IsNaN(East) &&
|
!double.IsNaN(West) && !double.IsNaN(East) &&
|
||||||
South < North && West < East)
|
South < North && West < East)
|
||||||
{
|
{
|
||||||
// Create a scaled RectangleGeometry due to inaccurate hit testing in WPF.
|
|
||||||
// See http://stackoverflow.com/a/19335624/1136211
|
|
||||||
|
|
||||||
const double scale = 1e6;
|
|
||||||
var p1 = ParentMap.MapTransform.Transform(new Location(South, West));
|
var p1 = ParentMap.MapTransform.Transform(new Location(South, West));
|
||||||
var p2 = ParentMap.MapTransform.Transform(new Location(North, East));
|
var p2 = ParentMap.MapTransform.Transform(new Location(North, East));
|
||||||
geometry.Rect = new Rect(p1.X * scale, p1.Y * scale, (p2.X - p1.X) * scale, (p2.Y - p1.Y) * scale);
|
|
||||||
|
|
||||||
var scaleTransform = new ScaleTransform // revert scaling
|
SetRect(new Rect(p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y));
|
||||||
{
|
|
||||||
ScaleX = 1d / scale,
|
|
||||||
ScaleY = 1d / scale
|
|
||||||
};
|
|
||||||
scaleTransform.Freeze();
|
|
||||||
|
|
||||||
var transform = new TransformGroup();
|
|
||||||
transform.Children.Add(scaleTransform);
|
|
||||||
transform.Children.Add(ParentMap.ViewportTransform);
|
|
||||||
RenderTransform = transform;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,11 @@ namespace MapControl
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PanelBase : Panel
|
public class PanelBase : Panel
|
||||||
{
|
{
|
||||||
#if WINDOWS_RUNTIME || SILVERLIGHT
|
|
||||||
protected internal UIElementCollection InternalChildren
|
|
||||||
{
|
|
||||||
get { return Children; }
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
{
|
{
|
||||||
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
||||||
|
|
||||||
foreach (UIElement element in InternalChildren)
|
foreach (UIElement element in Children)
|
||||||
{
|
{
|
||||||
element.Measure(availableSize);
|
element.Measure(availableSize);
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +33,7 @@ namespace MapControl
|
||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
{
|
{
|
||||||
foreach (UIElement child in InternalChildren)
|
foreach (UIElement child in Children)
|
||||||
{
|
{
|
||||||
child.Arrange(new Rect(new Point(), finalSize));
|
child.Arrange(new Rect(new Point(), finalSize));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
#if SILVERLIGHT
|
#if WINDOWS_PHONE
|
||||||
|
[assembly: AssemblyTitle("XAML Map Control (Windows Phone Silverlight)")]
|
||||||
|
[assembly: AssemblyDescription("XAML Map Control Library for Windows Phone Silverlight")]
|
||||||
|
#elif SILVERLIGHT
|
||||||
[assembly: AssemblyTitle("XAML Map Control (Silverlight)")]
|
[assembly: AssemblyTitle("XAML Map Control (Silverlight)")]
|
||||||
[assembly: AssemblyDescription("XAML Map Control Library for Silverlight")]
|
[assembly: AssemblyDescription("XAML Map Control Library for Silverlight")]
|
||||||
#else
|
#else
|
||||||
|
|
@ -14,8 +17,8 @@ using System.Windows;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
32
MapControl/Settings.cs
Normal file
32
MapControl/Settings.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||||
|
// Copyright © 2014 Clemens Fischer
|
||||||
|
// Licensed under the Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
#if WINDOWS_RUNTIME
|
||||||
|
using Windows.UI.Xaml.Media.Animation;
|
||||||
|
#else
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Stores global static properties that control the behaviour of the map control.
|
||||||
|
/// </summary>
|
||||||
|
public static class Settings
|
||||||
|
{
|
||||||
|
public static TimeSpan TileUpdateInterval { get; set; }
|
||||||
|
public static TimeSpan TileAnimationDuration { get; set; }
|
||||||
|
public static TimeSpan MapAnimationDuration { get; set; }
|
||||||
|
public static EasingFunctionBase MapAnimationEasingFunction { get; set; }
|
||||||
|
|
||||||
|
static Settings()
|
||||||
|
{
|
||||||
|
TileUpdateInterval = TimeSpan.FromSeconds(0.5);
|
||||||
|
TileAnimationDuration = TimeSpan.FromSeconds(0.3);
|
||||||
|
MapAnimationDuration = TimeSpan.FromSeconds(0.3);
|
||||||
|
MapAnimationEasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||||
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
|
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
|
||||||
<Setter Property="Padding" Value="3"/>
|
<Setter Property="Padding" Value="3"/>
|
||||||
|
<Setter Property="Foreground" Value="Black"/>
|
||||||
<Setter Property="Background" Value="White"/>
|
<Setter Property="Background" Value="White"/>
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ namespace MapControl
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation { To = 1d, Duration = AnimationDuration });
|
Image.BeginAnimation(Image.OpacityProperty,
|
||||||
|
new DoubleAnimation { To = 1d, Duration = Settings.TileAnimationDuration });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -55,7 +56,8 @@ namespace MapControl
|
||||||
bitmap.ImageOpened -= BitmapImageOpened;
|
bitmap.ImageOpened -= BitmapImageOpened;
|
||||||
bitmap.ImageFailed -= BitmapImageFailed;
|
bitmap.ImageFailed -= BitmapImageFailed;
|
||||||
|
|
||||||
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation { To = 1d, Duration = AnimationDuration });
|
Image.BeginAnimation(Image.OpacityProperty,
|
||||||
|
new DoubleAnimation { To = 1d, Duration = Settings.TileAnimationDuration });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BitmapImageFailed(object sender, ExceptionRoutedEventArgs e)
|
private void BitmapImageFailed(object sender, ExceptionRoutedEventArgs e)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ namespace MapControl
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
|
Image.BeginAnimation(Image.OpacityProperty,
|
||||||
|
new DoubleAnimation(1d, Settings.TileAnimationDuration));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -47,7 +48,8 @@ namespace MapControl
|
||||||
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
||||||
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
||||||
|
|
||||||
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
|
Image.BeginAnimation(Image.OpacityProperty,
|
||||||
|
new DoubleAnimation(1d, Settings.TileAnimationDuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BitmapDownloadFailed(object sender, ExceptionEventArgs e)
|
private void BitmapDownloadFailed(object sender, ExceptionEventArgs e)
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
public partial class Tile
|
public partial class Tile
|
||||||
{
|
{
|
||||||
public static TimeSpan AnimationDuration = TimeSpan.FromSeconds(0.5);
|
|
||||||
|
|
||||||
public readonly int ZoomLevel;
|
public readonly int ZoomLevel;
|
||||||
public readonly int X;
|
public readonly int X;
|
||||||
public readonly int Y;
|
public readonly int Y;
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,8 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
internal partial class TileContainer
|
internal partial class TileContainer
|
||||||
{
|
{
|
||||||
private Matrix GetTileIndexMatrix(int numTiles)
|
private Matrix GetTileIndexMatrix(double scale)
|
||||||
{
|
{
|
||||||
var scale = (double)numTiles / 360d;
|
|
||||||
|
|
||||||
return ViewportTransform.Matrix
|
return ViewportTransform.Matrix
|
||||||
.Invert() // view to map coordinates
|
.Invert() // view to map coordinates
|
||||||
.Translate(180d, -180d)
|
.Translate(180d, -180d)
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,8 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
internal partial class TileContainer
|
internal partial class TileContainer
|
||||||
{
|
{
|
||||||
private Matrix GetTileIndexMatrix(int numTiles)
|
private Matrix GetTileIndexMatrix(double scale)
|
||||||
{
|
{
|
||||||
var scale = (double)numTiles / 360d;
|
|
||||||
var transform = ViewportTransform.Matrix;
|
var transform = ViewportTransform.Matrix;
|
||||||
transform.Invert(); // view to map coordinates
|
transform.Invert(); // view to map coordinates
|
||||||
transform.Translate(180d, -180d);
|
transform.Translate(180d, -180d);
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,9 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
internal partial class TileContainer : PanelBase
|
internal partial class TileContainer : PanelBase
|
||||||
{
|
{
|
||||||
// relative scaled tile size ranges from 0.75 to 1.5 (192 to 384 pixels)
|
// relative size of scaled tile ranges from 0.75 to 1.5 (192 to 384 pixels)
|
||||||
private static double zoomLevelSwitchDelta = -Math.Log(0.75, 2d);
|
private static double zoomLevelSwitchDelta = -Math.Log(0.75, 2d);
|
||||||
|
|
||||||
public static TimeSpan UpdateInterval = TimeSpan.FromSeconds(0.5);
|
|
||||||
|
|
||||||
private readonly DispatcherTimer updateTimer;
|
private readonly DispatcherTimer updateTimer;
|
||||||
private Size viewportSize;
|
private Size viewportSize;
|
||||||
private Point viewportOrigin;
|
private Point viewportOrigin;
|
||||||
|
|
@ -38,26 +36,26 @@ namespace MapControl
|
||||||
public TileContainer()
|
public TileContainer()
|
||||||
{
|
{
|
||||||
RenderTransform = new MatrixTransform();
|
RenderTransform = new MatrixTransform();
|
||||||
updateTimer = new DispatcherTimer { Interval = UpdateInterval };
|
updateTimer = new DispatcherTimer { Interval = Settings.TileUpdateInterval };
|
||||||
updateTimer.Tick += UpdateTiles;
|
updateTimer.Tick += UpdateTiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<TileLayer> TileLayers
|
public IEnumerable<TileLayer> TileLayers
|
||||||
{
|
{
|
||||||
get { return InternalChildren.Cast<TileLayer>(); }
|
get { return Children.Cast<TileLayer>(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddTileLayers(int index, IEnumerable<TileLayer> tileLayers)
|
public void AddTileLayers(int index, IEnumerable<TileLayer> tileLayers)
|
||||||
{
|
{
|
||||||
foreach (var tileLayer in tileLayers)
|
foreach (var tileLayer in tileLayers)
|
||||||
{
|
{
|
||||||
if (index < InternalChildren.Count)
|
if (index < Children.Count)
|
||||||
{
|
{
|
||||||
InternalChildren.Insert(index, tileLayer);
|
Children.Insert(index, tileLayer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InternalChildren.Add(tileLayer);
|
Children.Add(tileLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
|
@ -69,19 +67,19 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
while (count-- > 0)
|
while (count-- > 0)
|
||||||
{
|
{
|
||||||
((TileLayer)InternalChildren[index]).ClearTiles();
|
((TileLayer)Children[index]).ClearTiles();
|
||||||
InternalChildren.RemoveAt(index);
|
Children.RemoveAt(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearTileLayers()
|
public void ClearTileLayers()
|
||||||
{
|
{
|
||||||
foreach (TileLayer tileLayer in InternalChildren)
|
foreach (TileLayer tileLayer in Children)
|
||||||
{
|
{
|
||||||
tileLayer.ClearTiles();
|
tileLayer.ClearTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalChildren.Clear();
|
Children.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point vpOrigin, Size vpSize)
|
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point vpOrigin, Size vpSize)
|
||||||
|
|
@ -127,7 +125,8 @@ namespace MapControl
|
||||||
updateTimer.Stop();
|
updateTimer.Stop();
|
||||||
|
|
||||||
var zoom = (int)Math.Floor(zoomLevel + zoomLevelSwitchDelta);
|
var zoom = (int)Math.Floor(zoomLevel + zoomLevelSwitchDelta);
|
||||||
var transform = GetTileIndexMatrix(1 << zoom);
|
var scale = (double)(1 << zoom) / 360d;
|
||||||
|
var transform = GetTileIndexMatrix(scale);
|
||||||
|
|
||||||
// tile indices of visible rectangle
|
// tile indices of visible rectangle
|
||||||
var p1 = transform.Transform(new Point(0d, 0d));
|
var p1 = transform.Transform(new Point(0d, 0d));
|
||||||
|
|
@ -149,7 +148,7 @@ namespace MapControl
|
||||||
|
|
||||||
UpdateRenderTransform();
|
UpdateRenderTransform();
|
||||||
|
|
||||||
foreach (TileLayer tileLayer in InternalChildren)
|
foreach (TileLayer tileLayer in Children)
|
||||||
{
|
{
|
||||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ namespace MapControl
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads map tile images.
|
/// Loads map tile images.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class TileImageLoader
|
internal class TileImageLoader : ITileImageLoader
|
||||||
{
|
{
|
||||||
internal void BeginGetTiles(TileLayer tileLayer, IEnumerable<Tile> tiles)
|
public void BeginLoadTiles(TileLayer tileLayer, IEnumerable<Tile> tiles)
|
||||||
{
|
{
|
||||||
var imageTileSource = tileLayer.TileSource as ImageTileSource;
|
var imageTileSource = tileLayer.TileSource as ImageTileSource;
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ namespace MapControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CancelGetTiles()
|
public void CancelLoadTiles(TileLayer tileLayer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
@ -20,7 +21,7 @@ namespace MapControl
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads map tile images and optionally caches them in a System.Runtime.Caching.ObjectCache.
|
/// Loads map tile images and optionally caches them in a System.Runtime.Caching.ObjectCache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TileImageLoader
|
public class TileImageLoader : ITileImageLoader
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default Name of an ObjectCache instance that is assigned to the Cache property.
|
/// Default Name of an ObjectCache instance that is assigned to the Cache property.
|
||||||
|
|
@ -33,39 +34,27 @@ namespace MapControl
|
||||||
public static readonly string DefaultCacheDirectory =
|
public static readonly string DefaultCacheDirectory =
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl");
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default expiration time span for cached images. Used when no expiration date
|
||||||
|
/// was transmitted on download. The default value is seven days.
|
||||||
|
/// </summary>
|
||||||
|
public static TimeSpan DefaultCacheExpiration { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ObjectCache used to cache tile images. The default is MemoryCache.Default.
|
/// The ObjectCache used to cache tile images. The default is MemoryCache.Default.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ObjectCache Cache { get; set; }
|
public static ObjectCache Cache { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The time interval after which cached images expire. The default value is seven days.
|
|
||||||
/// When an image is not retrieved from the cache during this interval it is considered as expired
|
|
||||||
/// and will be removed from the cache, provided that the cache implementation supports expiration.
|
|
||||||
/// If an image is retrieved from the cache and the CacheUpdateAge time interval has expired,
|
|
||||||
/// the image is downloaded again and rewritten to the cache with a new expiration time.
|
|
||||||
/// </summary>
|
|
||||||
public static TimeSpan CacheExpiration { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The time interval after which a cached image is updated and rewritten to the cache.
|
|
||||||
/// The default value is one day. This time interval should not be greater than the value
|
|
||||||
/// of the CacheExpiration property.
|
|
||||||
/// If CacheUpdateAge is less than or equal to TimeSpan.Zero, cached images are never updated.
|
|
||||||
/// </summary>
|
|
||||||
public static TimeSpan CacheUpdateAge { get; set; }
|
|
||||||
|
|
||||||
static TileImageLoader()
|
static TileImageLoader()
|
||||||
{
|
{
|
||||||
|
DefaultCacheExpiration = TimeSpan.FromDays(7);
|
||||||
Cache = MemoryCache.Default;
|
Cache = MemoryCache.Default;
|
||||||
CacheExpiration = TimeSpan.FromDays(7);
|
|
||||||
CacheUpdateAge = TimeSpan.FromDays(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ConcurrentQueue<Tile> pendingTiles = new ConcurrentQueue<Tile>();
|
private readonly ConcurrentQueue<Tile> pendingTiles = new ConcurrentQueue<Tile>();
|
||||||
private int threadCount;
|
private int threadCount;
|
||||||
|
|
||||||
internal void BeginGetTiles(TileLayer tileLayer, IEnumerable<Tile> tiles)
|
public void BeginLoadTiles(TileLayer tileLayer, IEnumerable<Tile> tiles)
|
||||||
{
|
{
|
||||||
if (tiles.Any())
|
if (tiles.Any())
|
||||||
{
|
{
|
||||||
|
|
@ -96,7 +85,7 @@ namespace MapControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CancelGetTiles()
|
public void CancelLoadTiles(TileLayer tileLayer)
|
||||||
{
|
{
|
||||||
Tile tile;
|
Tile tile;
|
||||||
while (pendingTiles.TryDequeue(out tile)) ; // no Clear method
|
while (pendingTiles.TryDequeue(out tile)) ; // no Clear method
|
||||||
|
|
@ -119,7 +108,7 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
pendingTiles.Enqueue(tile); // not yet cached
|
pendingTiles.Enqueue(tile); // not yet cached
|
||||||
}
|
}
|
||||||
else if (CacheUpdateAge > TimeSpan.Zero && TileCache.CreationTime(buffer) + CacheUpdateAge < DateTime.UtcNow)
|
else if (TileCache.IsExpired(buffer))
|
||||||
{
|
{
|
||||||
dispatcher.Invoke(setImageAction, tile, image); // synchronously before enqueuing
|
dispatcher.Invoke(setImageAction, tile, image); // synchronously before enqueuing
|
||||||
outdatedTiles.Add(tile); // update outdated cache
|
outdatedTiles.Add(tile); // update outdated cache
|
||||||
|
|
@ -154,7 +143,6 @@ namespace MapControl
|
||||||
|
|
||||||
while (pendingTiles.TryDequeue(out tile))
|
while (pendingTiles.TryDequeue(out tile))
|
||||||
{
|
{
|
||||||
byte[] buffer = null;
|
|
||||||
ImageSource image = null;
|
ImageSource image = null;
|
||||||
|
|
||||||
if (imageTileSource != null)
|
if (imageTileSource != null)
|
||||||
|
|
@ -167,14 +155,24 @@ namespace MapControl
|
||||||
|
|
||||||
if (uri != null)
|
if (uri != null)
|
||||||
{
|
{
|
||||||
if (uri.Scheme == "file") // create from FileStream because creating from URI leaves the file open
|
if (uri.Scheme == "file") // create from FileStream because creating from Uri leaves the file open
|
||||||
{
|
{
|
||||||
image = CreateImage(uri.LocalPath);
|
image = CreateImage(uri.LocalPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer = DownloadImage(uri);
|
DateTime expirationTime;
|
||||||
|
var buffer = DownloadImage(uri, out expirationTime);
|
||||||
|
|
||||||
image = CreateImage(buffer);
|
image = CreateImage(buffer);
|
||||||
|
|
||||||
|
if (image != null &&
|
||||||
|
Cache != null &&
|
||||||
|
!string.IsNullOrWhiteSpace(sourceName) &&
|
||||||
|
expirationTime > DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
Cache.Set(TileCache.Key(sourceName, tile), buffer, new CacheItemPolicy { AbsoluteExpiration = expirationTime });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -183,11 +181,6 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
dispatcher.BeginInvoke(setImageAction, tile, image);
|
dispatcher.BeginInvoke(setImageAction, tile, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image != null && buffer != null && Cache != null && !string.IsNullOrWhiteSpace(sourceName))
|
|
||||||
{
|
|
||||||
Cache.Set(TileCache.Key(sourceName, tile), buffer, new CacheItemPolicy { SlidingExpiration = CacheExpiration });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Interlocked.Decrement(ref threadCount);
|
Interlocked.Decrement(ref threadCount);
|
||||||
|
|
@ -253,20 +246,33 @@ namespace MapControl
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] DownloadImage(Uri uri)
|
private static byte[] DownloadImage(Uri uri, out DateTime expirationTime)
|
||||||
{
|
{
|
||||||
|
expirationTime = DateTime.UtcNow + DefaultCacheExpiration;
|
||||||
|
|
||||||
byte[] buffer = null;
|
byte[] buffer = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var request = (HttpWebRequest)WebRequest.Create(uri);
|
var request = HttpWebRequest.CreateHttp(uri);
|
||||||
request.UserAgent = "XAML Map Control";
|
|
||||||
|
|
||||||
using (var response = (HttpWebResponse)request.GetResponse())
|
using (var response = (HttpWebResponse)request.GetResponse())
|
||||||
using (var responseStream = response.GetResponseStream())
|
using (var responseStream = response.GetResponseStream())
|
||||||
{
|
{
|
||||||
buffer = TileCache.CreateBuffer(responseStream, (int)response.ContentLength);
|
var expiresHeader = response.Headers["Expires"];
|
||||||
|
DateTime expires;
|
||||||
|
|
||||||
|
if (expiresHeader != null &&
|
||||||
|
DateTime.TryParse(expiresHeader, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out expires) &&
|
||||||
|
expirationTime > expires)
|
||||||
|
{
|
||||||
|
expirationTime = expires;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = TileCache.CreateBuffer(responseStream, (int)response.ContentLength, expirationTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Trace.TraceInformation("Downloaded {0}, expires {1}", uri, expirationTime);
|
||||||
}
|
}
|
||||||
catch (WebException ex)
|
catch (WebException ex)
|
||||||
{
|
{
|
||||||
|
|
@ -305,18 +311,16 @@ namespace MapControl
|
||||||
return new MemoryStream(cacheBuffer, imageBufferOffset, cacheBuffer.Length - imageBufferOffset, false);
|
return new MemoryStream(cacheBuffer, imageBufferOffset, cacheBuffer.Length - imageBufferOffset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DateTime CreationTime(byte[] cacheBuffer)
|
public static bool IsExpired(byte[] cacheBuffer)
|
||||||
{
|
{
|
||||||
return DateTime.FromBinary(BitConverter.ToInt64(cacheBuffer, 0));
|
return DateTime.FromBinary(BitConverter.ToInt64(cacheBuffer, 0)) < DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] CreateBuffer(Stream imageStream, int length)
|
public static byte[] CreateBuffer(Stream imageStream, int length, DateTime expirationTime)
|
||||||
{
|
{
|
||||||
var creationTime = BitConverter.GetBytes(DateTime.UtcNow.ToBinary());
|
|
||||||
|
|
||||||
using (var memoryStream = length > 0 ? new MemoryStream(length + imageBufferOffset) : new MemoryStream())
|
using (var memoryStream = length > 0 ? new MemoryStream(length + imageBufferOffset) : new MemoryStream())
|
||||||
{
|
{
|
||||||
memoryStream.Write(creationTime, 0, imageBufferOffset);
|
memoryStream.Write(BitConverter.GetBytes(expirationTime.ToBinary()), 0, imageBufferOffset);
|
||||||
imageStream.CopyTo(memoryStream);
|
imageStream.CopyTo(memoryStream);
|
||||||
|
|
||||||
return length > 0 ? memoryStream.GetBuffer() : memoryStream.ToArray();
|
return length > 0 ? memoryStream.GetBuffer() : memoryStream.ToArray();
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,13 @@ namespace MapControl
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads map tile images.
|
/// Loads map tile images.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TileImageLoader
|
public class TileImageLoader : ITileImageLoader
|
||||||
{
|
{
|
||||||
public static IObjectCache Cache { get; set; }
|
public static IObjectCache Cache { get; set; }
|
||||||
|
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
|
|
||||||
internal void BeginGetTiles(TileLayer tileLayer, IEnumerable<Tile> tiles)
|
public void BeginLoadTiles(TileLayer tileLayer, IEnumerable<Tile> tiles)
|
||||||
{
|
{
|
||||||
var imageTileSource = tileLayer.TileSource as ImageTileSource;
|
var imageTileSource = tileLayer.TileSource as ImageTileSource;
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ namespace MapControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CancelGetTiles()
|
public void CancelLoadTiles(TileLayer tileLayer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,24 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
#if WINDOWS_RUNTIME
|
#if WINDOWS_RUNTIME
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
|
using Windows.UI.Xaml.Documents;
|
||||||
using Windows.UI.Xaml.Markup;
|
using Windows.UI.Xaml.Markup;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
#else
|
#else
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Documents;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace MapControl
|
namespace MapControl
|
||||||
{
|
{
|
||||||
|
public interface ITileImageLoader
|
||||||
|
{
|
||||||
|
void BeginLoadTiles(TileLayer tileLayer, IEnumerable<Tile> tiles);
|
||||||
|
void CancelLoadTiles(TileLayer tileLayer);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills a rectangular area with map tiles from a TileSource.
|
/// Fills a rectangular area with map tiles from a TileSource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -34,29 +42,35 @@ namespace MapControl
|
||||||
return new TileLayer
|
return new TileLayer
|
||||||
{
|
{
|
||||||
SourceName = "OpenStreetMap",
|
SourceName = "OpenStreetMap",
|
||||||
Description = "© {y} OpenStreetMap Contributors, CC-BY-SA",
|
Description="© [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)",
|
||||||
TileSource = new TileSource("http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png")
|
TileSource = new TileSource { UriFormat = "http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly TileImageLoader tileImageLoader = new TileImageLoader();
|
private readonly ITileImageLoader tileImageLoader;
|
||||||
private string description = string.Empty;
|
|
||||||
private TileSource tileSource;
|
private TileSource tileSource;
|
||||||
private List<Tile> tiles = new List<Tile>();
|
private List<Tile> tiles = new List<Tile>();
|
||||||
private Int32Rect grid;
|
|
||||||
private int zoomLevel;
|
private int zoomLevel;
|
||||||
|
private Int32Rect grid;
|
||||||
|
|
||||||
public TileLayer()
|
public TileLayer()
|
||||||
|
: this(new TileImageLoader())
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileLayer(ITileImageLoader tileImageLoader)
|
||||||
|
{
|
||||||
|
this.tileImageLoader = tileImageLoader;
|
||||||
MinZoomLevel = 0;
|
MinZoomLevel = 0;
|
||||||
MaxZoomLevel = 18;
|
MaxZoomLevel = 18;
|
||||||
MaxParallelDownloads = 8;
|
MaxParallelDownloads = 4;
|
||||||
LoadLowerZoomLevels = true;
|
LoadLowerZoomLevels = true;
|
||||||
AnimateTileOpacity = true;
|
AnimateTileOpacity = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SourceName { get; set; }
|
public string SourceName { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
public int MinZoomLevel { get; set; }
|
public int MinZoomLevel { get; set; }
|
||||||
public int MaxZoomLevel { get; set; }
|
public int MaxZoomLevel { get; set; }
|
||||||
public int MaxParallelDownloads { get; set; }
|
public int MaxParallelDownloads { get; set; }
|
||||||
|
|
@ -64,10 +78,14 @@ namespace MapControl
|
||||||
public bool AnimateTileOpacity { get; set; }
|
public bool AnimateTileOpacity { get; set; }
|
||||||
public Brush Foreground { get; set; }
|
public Brush Foreground { get; set; }
|
||||||
|
|
||||||
public string Description
|
/// <summary>
|
||||||
|
/// In case the Description text contains copyright links in markdown syntax [text](url),
|
||||||
|
/// the DescriptionInlines property may be used to create a collection of Run and Hyperlink
|
||||||
|
/// inlines to be displayed in e.g. a TextBlock or a Silverlight RichTextBlock.
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<Inline> DescriptionInlines
|
||||||
{
|
{
|
||||||
get { return description; }
|
get { return Description.ToInlines(); }
|
||||||
set { description = value.Replace("{y}", DateTime.Now.Year.ToString()); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileSource TileSource
|
public TileSource TileSource
|
||||||
|
|
@ -79,42 +97,43 @@ namespace MapControl
|
||||||
|
|
||||||
if (grid.Width > 0 && grid.Height > 0)
|
if (grid.Width > 0 && grid.Height > 0)
|
||||||
{
|
{
|
||||||
tileImageLoader.CancelGetTiles();
|
ClearTiles();
|
||||||
tiles.Clear();
|
UpdateTiles();
|
||||||
|
|
||||||
if (tileSource != null)
|
|
||||||
{
|
|
||||||
SelectTiles();
|
|
||||||
RenderTiles();
|
|
||||||
tileImageLoader.BeginGetTiles(this, tiles.Where(t => !t.HasImageSource));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RenderTiles();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateTiles(int zoomLevel, Int32Rect grid)
|
|
||||||
{
|
|
||||||
this.grid = grid;
|
|
||||||
this.zoomLevel = zoomLevel;
|
|
||||||
|
|
||||||
if (tileSource != null)
|
|
||||||
{
|
|
||||||
tileImageLoader.CancelGetTiles();
|
|
||||||
SelectTiles();
|
|
||||||
RenderTiles();
|
|
||||||
tileImageLoader.BeginGetTiles(this, tiles.Where(t => !t.HasImageSource));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ClearTiles()
|
internal void ClearTiles()
|
||||||
{
|
{
|
||||||
tileImageLoader.CancelGetTiles();
|
tileImageLoader.CancelLoadTiles(this);
|
||||||
tiles.Clear();
|
tiles.Clear();
|
||||||
RenderTiles();
|
Children.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UpdateTiles(int zoomLevel, Int32Rect grid)
|
||||||
|
{
|
||||||
|
this.zoomLevel = zoomLevel;
|
||||||
|
this.grid = grid;
|
||||||
|
|
||||||
|
UpdateTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTiles()
|
||||||
|
{
|
||||||
|
if (tileSource != null)
|
||||||
|
{
|
||||||
|
tileImageLoader.CancelLoadTiles(this);
|
||||||
|
|
||||||
|
SelectTiles();
|
||||||
|
Children.Clear();
|
||||||
|
|
||||||
|
foreach (var tile in tiles)
|
||||||
|
{
|
||||||
|
Children.Add(tile.Image);
|
||||||
|
}
|
||||||
|
|
||||||
|
tileImageLoader.BeginLoadTiles(this, tiles.Where(t => !t.HasImageSource));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectTiles()
|
private void SelectTiles()
|
||||||
|
|
@ -122,7 +141,9 @@ namespace MapControl
|
||||||
var maxZoomLevel = Math.Min(zoomLevel, MaxZoomLevel);
|
var maxZoomLevel = Math.Min(zoomLevel, MaxZoomLevel);
|
||||||
var minZoomLevel = maxZoomLevel;
|
var minZoomLevel = maxZoomLevel;
|
||||||
|
|
||||||
if (LoadLowerZoomLevels && Parent is TileContainer && ((TileContainer)Parent).TileLayers.FirstOrDefault() == this)
|
if (LoadLowerZoomLevels &&
|
||||||
|
Parent is TileContainer &&
|
||||||
|
((TileContainer)Parent).TileLayers.FirstOrDefault() == this)
|
||||||
{
|
{
|
||||||
minZoomLevel = MinZoomLevel;
|
minZoomLevel = MinZoomLevel;
|
||||||
}
|
}
|
||||||
|
|
@ -165,16 +186,6 @@ namespace MapControl
|
||||||
tiles = newTiles;
|
tiles = newTiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderTiles()
|
|
||||||
{
|
|
||||||
InternalChildren.Clear();
|
|
||||||
|
|
||||||
foreach (var tile in tiles)
|
|
||||||
{
|
|
||||||
InternalChildren.Add(tile.Image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
{
|
{
|
||||||
foreach (var tile in tiles)
|
foreach (var tile in tiles)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
|
||||||
#if WINDOWS_RUNTIME
|
#if WINDOWS_RUNTIME
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
#else
|
#else
|
||||||
|
|
@ -28,10 +27,9 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileSource(string uriFormat)
|
protected TileSource(string uriFormat)
|
||||||
: this()
|
|
||||||
{
|
{
|
||||||
UriFormat = uriFormat;
|
this.uriFormat = uriFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string UriFormat
|
public string UriFormat
|
||||||
|
|
@ -147,16 +145,16 @@ namespace MapControl
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = new StringBuilder { Length = zoomLevel };
|
var quadkey = new char[zoomLevel];
|
||||||
|
|
||||||
for (var z = zoomLevel - 1; z >= 0; z--, x /= 2, y /= 2)
|
for (var z = zoomLevel - 1; z >= 0; z--, x /= 2, y /= 2)
|
||||||
{
|
{
|
||||||
key[z] = (char)('0' + 2 * (y % 2) + (x % 2));
|
quadkey[z] = (char)('0' + 2 * (y % 2) + (x % 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Uri(uriFormat.
|
return new Uri(uriFormat.
|
||||||
Replace("{i}", key.ToString(key.Length - 1, 1)).
|
Replace("{i}", new string(quadkey[zoomLevel - 1], 1)).
|
||||||
Replace("{q}", key.ToString()));
|
Replace("{q}", new string(quadkey)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uri GetBoundingBoxUri(int x, int y, int zoomLevel)
|
private Uri GetBoundingBoxUri(int x, int y, int zoomLevel)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace MapControl
|
||||||
|
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
return new TileSource(value as string);
|
return new TileSource { UriFormat = value as string };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,21 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="..\BingMapsTileLayer.cs">
|
||||||
|
<Link>BingMapsTileLayer.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\BingMapsTileSource.cs">
|
||||||
|
<Link>BingMapsTileSource.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Extensions.Silverlight.WinRT.cs">
|
<Compile Include="..\Extensions.Silverlight.WinRT.cs">
|
||||||
<Link>Extensions.Silverlight.WinRT.cs</Link>
|
<Link>Extensions.Silverlight.WinRT.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Extensions.WinRT.cs">
|
<Compile Include="..\Extensions.WinRT.cs">
|
||||||
<Link>Extensions.WinRT.cs</Link>
|
<Link>Extensions.WinRT.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\HyperlinkText.cs">
|
||||||
|
<Link>HyperlinkText.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\ImageFileCache.WinRT.cs">
|
<Compile Include="..\ImageFileCache.WinRT.cs">
|
||||||
<Link>ImageFileCache.WinRT.cs</Link>
|
<Link>ImageFileCache.WinRT.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -120,6 +129,9 @@
|
||||||
<Compile Include="..\MapRectangle.cs">
|
<Compile Include="..\MapRectangle.cs">
|
||||||
<Link>MapRectangle.cs</Link>
|
<Link>MapRectangle.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MapRectangle.Silverlight.WinRT.cs">
|
||||||
|
<Link>MapRectangle.Silverlight.WinRT.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MapTransform.cs">
|
<Compile Include="..\MapTransform.cs">
|
||||||
<Link>MapTransform.cs</Link>
|
<Link>MapTransform.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -132,6 +144,9 @@
|
||||||
<Compile Include="..\Pushpin.Silverlight.WinRT.cs">
|
<Compile Include="..\Pushpin.Silverlight.WinRT.cs">
|
||||||
<Link>Pushpin.Silverlight.WinRT.cs</Link>
|
<Link>Pushpin.Silverlight.WinRT.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Settings.cs">
|
||||||
|
<Link>Settings.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Tile.cs">
|
<Compile Include="..\Tile.cs">
|
||||||
<Link>Tile.cs</Link>
|
<Link>Tile.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -163,16 +178,17 @@
|
||||||
<Link>MapControl.snk</Link>
|
<Link>MapControl.snk</Link>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Page Include="Themes\Generic.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</Page>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<TargetPlatform Include="Windows, Version=8.1" />
|
<TargetPlatform Include="Windows, Version=8.1" />
|
||||||
<TargetPlatform Include="WindowsPhoneApp, Version=8.1" />
|
<TargetPlatform Include="WindowsPhoneApp, Version=8.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Include="Themes\Generic.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
||||||
<VisualStudioVersion>12.0</VisualStudioVersion>
|
<VisualStudioVersion>12.0</VisualStudioVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||||
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
|
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
|
||||||
<Setter Property="Padding" Value="3"/>
|
<Setter Property="Padding" Value="3"/>
|
||||||
|
<Setter Property="Foreground" Value="Black"/>
|
||||||
<Setter Property="Background" Value="White"/>
|
<Setter Property="Background" Value="White"/>
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using Windows.ApplicationModel.Activation;
|
using Windows.ApplicationModel.Activation;
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Media.Animation;
|
using Windows.UI.Xaml.Media.Animation;
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,30 +7,58 @@
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
<map:TileLayerCollection x:Key="TileLayers">
|
<map:TileLayerCollection x:Key="TileLayers">
|
||||||
<map:TileLayer SourceName="OpenStreetMap" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
|
<!--
|
||||||
|
TileLayers with OpenStreetMap data.
|
||||||
|
-->
|
||||||
|
<map:TileLayer SourceName="OpenStreetMap"
|
||||||
|
Description="Maps © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
MaxZoomLevel="19">
|
||||||
<map:TileSource UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
<map:TileSource UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="OpenCycleMap" Description="OpenCycleMap - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
<map:TileLayer SourceName="Thunderforest OpenCycleMap"
|
||||||
<map:TileSource UriFormat="http://{c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"/>
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="OCM Transport" Description="OpenCycleMap Transport - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
<map:TileLayer SourceName="Thunderforest Landscape"
|
||||||
<map:TileSource UriFormat="http://{c}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png"/>
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="OCM Landscape" Description="OpenCycleMap Landscape - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
<map:TileLayer SourceName="Thunderforest Outdoors"
|
||||||
<map:TileSource UriFormat="http://{c}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png"/>
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors">
|
<map:TileLayer SourceName="Thunderforest Transport"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png"/>
|
||||||
|
</map:TileLayer>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Transport Dark"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png"/>
|
||||||
|
</map:TileLayer>
|
||||||
|
<map:TileLayer SourceName="MapQuest OpenStreetMap"
|
||||||
|
Description="Maps © [MapQuest](http://www.mapquest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
<map:TileSource UriFormat="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
<map:TileSource UriFormat="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="Google Maps" Description="Google Maps - © {y} Google" MaxZoomLevel="20">
|
<map:TileLayer SourceName="Seamarks" Description="© OpenSeaMap Contributors"
|
||||||
<map:TileSource UriFormat="http://mt{i}.google.com/vt/x={x}&y={y}&z={z}"/>
|
MinZoomLevel="10" MaxZoomLevel="18">
|
||||||
</map:TileLayer>
|
|
||||||
<map:TileLayer SourceName="Bing Maps" Description="Bing Maps - © {y} Microsoft Corporation" MinZoomLevel="1" MaxZoomLevel="19">
|
|
||||||
<map:TileSource UriFormat="http://ecn.t{i}.tiles.virtualearth.net/tiles/r{q}.png?g=0&stl=h"/>
|
|
||||||
</map:TileLayer>
|
|
||||||
<map:TileLayer SourceName="Seamarks" Description="© {y} OpenSeaMap Contributors, CC-BY-SA" MinZoomLevel="10" MaxZoomLevel="18">
|
|
||||||
<map:TileSource UriFormat="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"/>
|
<map:TileSource UriFormat="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Bing Maps TileLayers with tile URLs retrieved from the Imagery Metadata Service
|
||||||
|
(see http://msdn.microsoft.com/en-us/library/ff701716.aspx).
|
||||||
|
A Bing Maps API Key (see http://msdn.microsoft.com/en-us/library/ff428642.aspx) is required
|
||||||
|
for using these layers and must be assigned to the static BingMapsTileLayer.ApiKey property.
|
||||||
|
-->
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Road"
|
||||||
|
Description="Bing Maps - © Microsoft Corporation"
|
||||||
|
Mode="Road" MaxZoomLevel="19"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Aerial"
|
||||||
|
Description="Bing Maps - © Microsoft Corporation"
|
||||||
|
Mode="Aerial" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Hybrid"
|
||||||
|
Description="Bing Maps - © Microsoft Corporation"
|
||||||
|
Mode="AerialWithLabels" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
</map:TileLayerCollection>
|
</map:TileLayerCollection>
|
||||||
<local:ObjectReferenceConverter x:Key="ObjectReferenceConverter"/>
|
<local:ObjectReferenceConverter x:Key="ObjectReferenceConverter"/>
|
||||||
</Page.Resources>
|
</Page.Resources>
|
||||||
|
|
@ -43,6 +71,7 @@
|
||||||
<map:MapBase.Center>
|
<map:MapBase.Center>
|
||||||
<map:Location Latitude="53.5" Longitude="8.2"/>
|
<map:Location Latitude="53.5" Longitude="8.2"/>
|
||||||
</map:MapBase.Center>
|
</map:MapBase.Center>
|
||||||
|
|
||||||
<map:MapGraticule Opacity="0.6"/>
|
<map:MapGraticule Opacity="0.6"/>
|
||||||
|
|
||||||
<Canvas map:MapPanel.Location="{Binding Location}"
|
<Canvas map:MapPanel.Location="{Binding Location}"
|
||||||
|
|
@ -65,7 +94,12 @@
|
||||||
</Path>
|
</Path>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</map:MapBase>
|
</map:MapBase>
|
||||||
|
|
||||||
|
<Border HorizontalAlignment="Stretch" VerticalAlignment="Top" Background="#7F000000">
|
||||||
|
<TextBlock x:Name="mapLegend" Margin="2" FontSize="12"/>
|
||||||
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Page.BottomAppBar>
|
<Page.BottomAppBar>
|
||||||
<CommandBar>
|
<CommandBar>
|
||||||
<AppBarButton Label="Map">
|
<AppBarButton Label="Map">
|
||||||
|
|
@ -83,13 +117,16 @@
|
||||||
</AppBarButton.Icon>
|
</AppBarButton.Icon>
|
||||||
<AppBarButton.Flyout>
|
<AppBarButton.Flyout>
|
||||||
<MenuFlyout>
|
<MenuFlyout>
|
||||||
<MenuFlyoutItem Text="OpenStreetMap" Click="MapMenuItemClick"/>
|
<MenuFlyoutItem Text="OpenStreetMap" Tag="OpenStreetMap" Click="MapMenuItemClick"/>
|
||||||
<MenuFlyoutItem Text="OpenCycleMap" Click="MapMenuItemClick"/>
|
<MenuFlyoutItem Text="OpenCycleMap" Tag="Thunderforest OpenCycleMap" Click="MapMenuItemClick"/>
|
||||||
<MenuFlyoutItem Text="OCM Transport" Click="MapMenuItemClick"/>
|
<MenuFlyoutItem Text="Landscape" Tag="Thunderforest Landscape" Click="MapMenuItemClick"/>
|
||||||
<MenuFlyoutItem Text="OCM Landscape" Click="MapMenuItemClick"/>
|
<MenuFlyoutItem Text="Outdoors" Tag="Thunderforest Outdoors" Click="MapMenuItemClick"/>
|
||||||
<MenuFlyoutItem Text="MapQuest OSM" Click="MapMenuItemClick"/>
|
<MenuFlyoutItem Text="Transport" Tag="Thunderforest Transport" Click="MapMenuItemClick"/>
|
||||||
<!--<MenuFlyoutItem Text="Google Maps" Click="MapMenuItemClick"/>
|
<MenuFlyoutItem Text="Transport Dark" Tag="Thunderforest Transport Dark" Click="MapMenuItemClick"/>
|
||||||
<MenuFlyoutItem Text="Bing Maps" Click="MapMenuItemClick"/>-->
|
<MenuFlyoutItem Text="MapQuest Open" Tag="MapQuest OpenStreetMap" Click="MapMenuItemClick"/>
|
||||||
|
<!--<MenuFlyoutItem Text="Bing Maps Road" Tag="Bing Maps Road" Click="MapMenuItemClick"/>
|
||||||
|
<MenuFlyoutItem Text="Bing Maps Aerial" Tag="Bing Maps Aerial" Click="MapMenuItemClick"/>
|
||||||
|
<MenuFlyoutItem Text="Bing Maps Hybrid" Tag="Bing Maps Hybrid" Click="MapMenuItemClick"/>-->
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</AppBarButton.Flyout>
|
</AppBarButton.Flyout>
|
||||||
</AppBarButton>
|
</AppBarButton>
|
||||||
|
|
|
||||||
|
|
@ -10,38 +10,49 @@ namespace PhoneApplication
|
||||||
{
|
{
|
||||||
public sealed partial class MainPage : Page
|
public sealed partial class MainPage : Page
|
||||||
{
|
{
|
||||||
|
private TileLayerCollection tileLayers;
|
||||||
private bool manipulationActive;
|
private bool manipulationActive;
|
||||||
|
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
TileImageLoader.Cache = new ImageFileCache();
|
TileImageLoader.Cache = new ImageFileCache();
|
||||||
|
//BingMapsTileLayer.ApiKey = ...
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||||
map.TileLayer = tileLayers[0];
|
SetTileLayer(tileLayers[0].SourceName);
|
||||||
|
|
||||||
DataContext = new ViewModel(Dispatcher);
|
DataContext = new ViewModel(Dispatcher);
|
||||||
NavigationCacheMode = NavigationCacheMode.Required;
|
NavigationCacheMode = NavigationCacheMode.Required;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetTileLayer(string tileLayer)
|
||||||
|
{
|
||||||
|
map.TileLayer = tileLayers[tileLayer];
|
||||||
|
|
||||||
|
mapLegend.Inlines.Clear();
|
||||||
|
|
||||||
|
foreach (var inline in map.TileLayer.DescriptionInlines)
|
||||||
|
{
|
||||||
|
mapLegend.Inlines.Add(inline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
|
||||||
map.TileLayers.Add((TileLayer)tileLayers["Seamarks"]);
|
map.TileLayers.Add((TileLayer)tileLayers["Seamarks"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
|
||||||
map.TileLayers.Remove((TileLayer)tileLayers["Seamarks"]);
|
map.TileLayers.Remove((TileLayer)tileLayers["Seamarks"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapMenuItemClick(object sender, RoutedEventArgs e)
|
private void MapMenuItemClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectedValue = ((MenuFlyoutItem)sender).Text;
|
var selectedItem = (MenuFlyoutItem)sender;
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
SetTileLayer((string)selectedItem.Tag);
|
||||||
map.TileLayer = tileLayers[selectedValue];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CenterButtonClick(object sender, RoutedEventArgs e)
|
private void CenterButtonClick(object sender, RoutedEventArgs e)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,7 @@ namespace PhoneApplication
|
||||||
if (args.Status != PositionStatus.Initializing &&
|
if (args.Status != PositionStatus.Initializing &&
|
||||||
args.Status != PositionStatus.Ready)
|
args.Status != PositionStatus.Ready)
|
||||||
{
|
{
|
||||||
await dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
|
await dispatcher.RunAsync(CoreDispatcherPriority.Low, () => Location = null);
|
||||||
{
|
|
||||||
Location = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
|
|
@ -4,25 +4,58 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
|
||||||
xmlns:map="clr-namespace:MapControl;assembly=MapControl.Silverlight"
|
xmlns:map="clr-namespace:MapControl;assembly=MapControl.Silverlight"
|
||||||
xmlns:vm="clr-namespace:ViewModel"
|
xmlns:vm="clr-namespace:ViewModel"
|
||||||
xmlns:local="clr-namespace:SilverlightApplication"
|
xmlns:local="clr-namespace:SilverlightApplication"
|
||||||
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">
|
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<map:TileLayerCollection x:Key="TileLayers">
|
<map:TileLayerCollection x:Key="TileLayers">
|
||||||
<map:TileLayer SourceName="OpenStreetMap" Description="© {y} OpenStreetMap Contributors, CC-BY-SA"
|
<!--
|
||||||
TileSource="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
TileLayers with OpenStreetMap data.
|
||||||
<map:TileLayer SourceName="OpenCycleMap" Description="OpenCycleMap - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
-->
|
||||||
TileSource="http://{c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"/>
|
<map:TileLayer SourceName="OpenStreetMap"
|
||||||
<map:TileLayer SourceName="OCM Transport" Description="OpenCycleMap Transport - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
Description="Maps © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
TileSource="http://{c}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png"/>
|
TileSource="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
<map:TileLayer SourceName="OCM Landscape" Description="OpenCycleMap Landscape - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
MaxZoomLevel="19"/>
|
||||||
TileSource="http://{c}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png"/>
|
<map:TileLayer SourceName="Thunderforest OpenCycleMap"
|
||||||
<map:TileLayer SourceName="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors"
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
TileSource="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
TileSource="http://{c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png"/>
|
||||||
<map:TileLayer SourceName="Seamarks" Description="© {y} OpenSeaMap Contributors, CC-BY-SA"
|
<map:TileLayer SourceName="Thunderforest Landscape"
|
||||||
TileSource="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png" MinZoomLevel="10" MaxZoomLevel="18"/>
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png"/>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Outdoors"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png"/>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Transport"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png"/>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Transport Dark"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png"
|
||||||
|
Background="Black" Foreground="White"/>
|
||||||
|
<map:TileLayer SourceName="MapQuest OpenStreetMap"
|
||||||
|
Description="Maps © [MapQuest](http://www.mapquest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"
|
||||||
|
MaxZoomLevel="19"/>
|
||||||
|
<map:TileLayer SourceName="Seamarks"
|
||||||
|
TileSource="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"
|
||||||
|
MinZoomLevel="10" MaxZoomLevel="18"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Bing Maps TileLayers with tile URLs retrieved from the Imagery Metadata Service
|
||||||
|
(see http://msdn.microsoft.com/en-us/library/ff701716.aspx).
|
||||||
|
A Bing Maps API Key (see http://msdn.microsoft.com/en-us/library/ff428642.aspx) is required
|
||||||
|
for using these layers and must be assigned to the static BingMapsTileLayer.ApiKey property.
|
||||||
|
-->
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Road"
|
||||||
|
Description="© [Microsoft Corporation](http://www.bing.com/maps/)"
|
||||||
|
Mode="Road" MaxZoomLevel="19"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Aerial"
|
||||||
|
Description="© [Microsoft Corporation](http://www.bing.com/maps/)"
|
||||||
|
Mode="Aerial" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Hybrid"
|
||||||
|
Description="© [Microsoft Corporation](http://www.bing.com/maps/)"
|
||||||
|
Mode="AerialWithLabels" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
</map:TileLayerCollection>
|
</map:TileLayerCollection>
|
||||||
<DataTemplate x:Key="PolylineItemTemplate">
|
<DataTemplate x:Key="PolylineItemTemplate">
|
||||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||||
|
|
@ -127,9 +160,10 @@
|
||||||
|
|
||||||
<map:Pushpin map:MapPanel.Location="53.5,8.2" Background="Yellow" Foreground="Blue" Content="N 53° 30' E 8° 12'"/>
|
<map:Pushpin map:MapPanel.Location="53.5,8.2" Background="Yellow" Foreground="Blue" Content="N 53° 30' E 8° 12'"/>
|
||||||
|
|
||||||
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="4" FontSize="10"
|
|
||||||
Text="{Binding TileLayer.Description, ElementName=map}"/>
|
|
||||||
</map:Map>
|
</map:Map>
|
||||||
|
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#7FFFFFFF">
|
||||||
|
<RichTextBlock x:Name="mapLegend" Margin="4,2" FontSize="10"/>
|
||||||
|
</Border>
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
|
|
@ -154,13 +188,20 @@
|
||||||
<Slider Width="100" Minimum="0" Maximum="1"
|
<Slider Width="100" Minimum="0" Maximum="1"
|
||||||
Value="{Binding Opacity, ElementName=mapImage, Mode=TwoWay}"/>
|
Value="{Binding Opacity, ElementName=mapImage, Mode=TwoWay}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<CheckBox Margin="5" VerticalAlignment="Bottom" Content="Seamarks" Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
<CheckBox Margin="5" VerticalAlignment="Bottom" Content="Seamarks"
|
||||||
<ComboBox x:Name="tileLayerComboBox" Margin="5" VerticalAlignment="Bottom" Width="120" SelectionChanged="TileLayerSelectionChanged">
|
Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
||||||
<sys:String>OpenStreetMap</sys:String>
|
<ComboBox x:Name="tileLayerComboBox" Width="130" Margin="5" VerticalAlignment="Bottom"
|
||||||
<sys:String>OpenCycleMap</sys:String>
|
SelectionChanged="TileLayerSelectionChanged">
|
||||||
<sys:String>OCM Transport</sys:String>
|
<ComboBoxItem Tag="OpenStreetMap">OpenStreetMap</ComboBoxItem>
|
||||||
<sys:String>OCM Landscape</sys:String>
|
<ComboBoxItem Tag="Thunderforest OpenCycleMap">OpenCycleMap</ComboBoxItem>
|
||||||
<sys:String>MapQuest OSM</sys:String>
|
<ComboBoxItem Tag="Thunderforest Landscape">Landscape</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest Outdoors">Outdoors</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest Transport">Transport</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest Transport Dark">Transport Dark</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="MapQuest OpenStreetMap">MapQuest Open</ComboBoxItem>
|
||||||
|
<!--<ComboBoxItem Tag="Bing Maps Road">Bing Maps Road</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Bing Maps Aerial">Bing Maps Aerial</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Bing Maps Hybrid">Bing Maps Hybrid</ComboBoxItem>-->
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Documents;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using MapControl;
|
using MapControl;
|
||||||
|
|
||||||
|
|
@ -9,9 +10,15 @@ namespace SilverlightApplication
|
||||||
{
|
{
|
||||||
public partial class MainPage : UserControl
|
public partial class MainPage : UserControl
|
||||||
{
|
{
|
||||||
|
private TileLayerCollection tileLayers;
|
||||||
|
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
|
//BingMapsTileLayer.ApiKey = ...
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||||
tileLayerComboBox.SelectedIndex = 0;
|
tileLayerComboBox.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,19 +55,29 @@ namespace SilverlightApplication
|
||||||
|
|
||||||
private void TileLayerSelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void TileLayerSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
var comboBox = (ComboBox)sender;
|
var selectedItem = (ComboBoxItem)tileLayerComboBox.SelectedItem;
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
|
||||||
map.TileLayer = tileLayers[(string)comboBox.SelectedItem];
|
map.TileLayer = tileLayers[(string)selectedItem.Tag];
|
||||||
|
|
||||||
|
var paragraph = new Paragraph();
|
||||||
|
|
||||||
|
foreach (var inline in map.TileLayer.DescriptionInlines)
|
||||||
|
{
|
||||||
|
paragraph.Inlines.Add(inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
mapLegend.Blocks.Clear();
|
||||||
|
mapLegend.Blocks.Add(paragraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
map.TileLayers.Add((TileLayer)((TileLayerCollection)Resources["TileLayers"])["Seamarks"]);
|
map.TileLayers.Add(tileLayers["Seamarks"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
map.TileLayers.Remove((TileLayer)((TileLayerCollection)Resources["TileLayers"])["Seamarks"]);
|
map.TileLayers.Remove(tileLayers["Seamarks"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
|
|
@ -7,30 +7,58 @@
|
||||||
xmlns:local="using:StoreApplication">
|
xmlns:local="using:StoreApplication">
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
<map:TileLayerCollection x:Key="TileLayers">
|
<map:TileLayerCollection x:Key="TileLayers">
|
||||||
<map:TileLayer SourceName="OpenStreetMap" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
|
<!--
|
||||||
|
TileLayers with OpenStreetMap data.
|
||||||
|
-->
|
||||||
|
<map:TileLayer SourceName="OpenStreetMap"
|
||||||
|
Description="Maps © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
MaxZoomLevel="19">
|
||||||
<map:TileSource UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
<map:TileSource UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="OpenCycleMap" Description="OpenCycleMap - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
<map:TileLayer SourceName="Thunderforest OpenCycleMap"
|
||||||
<map:TileSource UriFormat="http://{c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"/>
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="OCM Transport" Description="OpenCycleMap Transport - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
<map:TileLayer SourceName="Thunderforest Landscape"
|
||||||
<map:TileSource UriFormat="http://{c}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png"/>
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="OCM Landscape" Description="OpenCycleMap Landscape - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
<map:TileLayer SourceName="Thunderforest Outdoors"
|
||||||
<map:TileSource UriFormat="http://{c}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png"/>
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<map:TileLayer SourceName="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors">
|
<map:TileLayer SourceName="Thunderforest Transport"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png"/>
|
||||||
|
</map:TileLayer>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Transport Dark"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
|
<map:TileSource UriFormat="http://{c}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png"/>
|
||||||
|
</map:TileLayer>
|
||||||
|
<map:TileLayer SourceName="MapQuest OpenStreetMap"
|
||||||
|
Description="Maps © [MapQuest](http://www.mapquest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
<map:TileSource UriFormat="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
<map:TileSource UriFormat="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
<!--<map:TileLayer SourceName="Bing Maps" Description="Bing Maps - © {y} Microsoft Corporation" MinZoomLevel="1" MaxZoomLevel="19">
|
<map:TileLayer SourceName="Seamarks" Description="© OpenSeaMap Contributors"
|
||||||
<map:TileSource UriFormat="http://ecn.t{i}.tiles.virtualearth.net/tiles/r{q}.png?g=0&stl=h"/>
|
MinZoomLevel="10" MaxZoomLevel="18">
|
||||||
</map:TileLayer>
|
|
||||||
<map:TileLayer SourceName="Bing Images" Description="Bing Maps - © {y} Microsoft Corporation" MinZoomLevel="1" MaxZoomLevel="19" Background="#FF3F3F3F" Foreground="White">
|
|
||||||
<map:TileSource UriFormat="http://ecn.t{i}.tiles.virtualearth.net/tiles/a{q}.jpeg?g=0"/>
|
|
||||||
</map:TileLayer>-->
|
|
||||||
<map:TileLayer SourceName="Seamarks" Description="© {y} OpenSeaMap Contributors, CC-BY-SA" MinZoomLevel="10" MaxZoomLevel="18">
|
|
||||||
<map:TileSource UriFormat="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"/>
|
<map:TileSource UriFormat="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>
|
</map:TileLayer>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Bing Maps TileLayers with tile URLs retrieved from the Imagery Metadata Service
|
||||||
|
(see http://msdn.microsoft.com/en-us/library/ff701716.aspx).
|
||||||
|
A Bing Maps API Key (see http://msdn.microsoft.com/en-us/library/ff428642.aspx) is required
|
||||||
|
for using these layers and must be assigned to the static BingMapsTileLayer.ApiKey property.
|
||||||
|
-->
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Road"
|
||||||
|
Description="Bing Maps - © Microsoft Corporation"
|
||||||
|
Mode="Road" MaxZoomLevel="19"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Aerial"
|
||||||
|
Description="Bing Maps - © Microsoft Corporation"
|
||||||
|
Mode="Aerial" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Hybrid"
|
||||||
|
Description="Bing Maps - © Microsoft Corporation"
|
||||||
|
Mode="AerialWithLabels" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
</map:TileLayerCollection>
|
</map:TileLayerCollection>
|
||||||
<DataTemplate x:Key="PolylineItemTemplate">
|
<DataTemplate x:Key="PolylineItemTemplate">
|
||||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||||
|
|
@ -162,10 +190,10 @@
|
||||||
<map:Location Latitude="53.5" Longitude="8.2"/>
|
<map:Location Latitude="53.5" Longitude="8.2"/>
|
||||||
</map:MapPanel.Location>
|
</map:MapPanel.Location>
|
||||||
</map:Pushpin>
|
</map:Pushpin>
|
||||||
|
|
||||||
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="4" FontSize="10"
|
|
||||||
Text="{Binding TileLayer.Description, ElementName=map}"/>
|
|
||||||
</map:Map>
|
</map:Map>
|
||||||
|
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#BFFFFFFF">
|
||||||
|
<TextBlock x:Name="mapLegend" Margin="2" FontSize="10" Foreground="Black"/>
|
||||||
|
</Border>
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
|
|
@ -188,16 +216,20 @@
|
||||||
<TextBlock Text="Image Opacity" HorizontalAlignment="Center" Foreground="Gray" FontSize="14"/>
|
<TextBlock Text="Image Opacity" HorizontalAlignment="Center" Foreground="Gray" FontSize="14"/>
|
||||||
<Slider Margin="10,-10,10,-10" Width="200" Value="50" ValueChanged="ImageOpacitySliderValueChanged"/>
|
<Slider Margin="10,-10,10,-10" Width="200" Value="50" ValueChanged="ImageOpacitySliderValueChanged"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<CheckBox Margin="10" VerticalAlignment="Center" Content="Seamarks" Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
<CheckBox Margin="10" VerticalAlignment="Center" Content="Seamarks"
|
||||||
<ComboBox Margin="10" Width="200" VerticalAlignment="Center" SelectedValuePath="Content"
|
Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
||||||
Loaded="TileLayerComboBoxLoaded" SelectionChanged="TileLayerSelectionChanged">
|
<ComboBox x:Name="tileLayerComboBox" Width="200" Margin="10" VerticalAlignment="Center"
|
||||||
<ComboBoxItem>OpenStreetMap</ComboBoxItem>
|
SelectionChanged="TileLayerSelectionChanged">
|
||||||
<ComboBoxItem>OpenCycleMap</ComboBoxItem>
|
<ComboBoxItem Tag="OpenStreetMap">OpenStreetMap</ComboBoxItem>
|
||||||
<ComboBoxItem>OCM Transport</ComboBoxItem>
|
<ComboBoxItem Tag="Thunderforest OpenCycleMap">OpenCycleMap</ComboBoxItem>
|
||||||
<ComboBoxItem>OCM Landscape</ComboBoxItem>
|
<ComboBoxItem Tag="Thunderforest Landscape">Landscape</ComboBoxItem>
|
||||||
<ComboBoxItem>MapQuest OSM</ComboBoxItem>
|
<ComboBoxItem Tag="Thunderforest Outdoors">Outdoors</ComboBoxItem>
|
||||||
<!--<ComboBoxItem>Bing Maps</ComboBoxItem>
|
<ComboBoxItem Tag="Thunderforest Transport">Transport</ComboBoxItem>
|
||||||
<ComboBoxItem>Bing Images</ComboBoxItem>-->
|
<ComboBoxItem Tag="Thunderforest Transport Dark">Transport Dark</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="MapQuest OpenStreetMap">MapQuest Open</ComboBoxItem>
|
||||||
|
<!--<ComboBoxItem Tag="Bing Maps Road">Bing Maps Road</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Bing Maps Aerial">Bing Maps Aerial</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Bing Maps Hybrid">Bing Maps Hybrid</ComboBoxItem>-->
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using MapControl;
|
using MapControl;
|
||||||
using Windows.Storage;
|
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
using Windows.UI.Xaml.Controls.Primitives;
|
||||||
|
|
@ -8,14 +7,17 @@ namespace StoreApplication
|
||||||
{
|
{
|
||||||
public sealed partial class MainPage : Page
|
public sealed partial class MainPage : Page
|
||||||
{
|
{
|
||||||
|
private TileLayerCollection tileLayers;
|
||||||
|
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
TileImageLoader.Cache = new ImageFileCache();
|
TileImageLoader.Cache = new ImageFileCache();
|
||||||
|
//BingMapsTileLayer.ApiKey = ...
|
||||||
|
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
|
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||||
map.TileLayer = tileLayers[0];
|
tileLayerComboBox.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImageOpacitySliderValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
private void ImageOpacitySliderValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
||||||
|
|
@ -26,28 +28,28 @@ namespace StoreApplication
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TileLayerComboBoxLoaded(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
((ComboBox)sender).SelectedIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TileLayerSelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void TileLayerSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
var selectedValue = (string)((ComboBox)sender).SelectedValue;
|
var selectedItem = (ComboBoxItem)tileLayerComboBox.SelectedItem;
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
|
||||||
map.TileLayer = tileLayers[selectedValue];
|
map.TileLayer = tileLayers[(string)selectedItem.Tag];
|
||||||
|
|
||||||
|
mapLegend.Inlines.Clear();
|
||||||
|
|
||||||
|
foreach (var inline in map.TileLayer.DescriptionInlines)
|
||||||
|
{
|
||||||
|
mapLegend.Inlines.Add(inline);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
map.TileLayers.Add(tileLayers["Seamarks"]);
|
||||||
map.TileLayers.Add((TileLayer)tileLayers["Seamarks"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
map.TileLayers.Remove(tileLayers["Seamarks"]);
|
||||||
map.TileLayers.Remove((TileLayer)tileLayers["Seamarks"]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
|
|
@ -9,48 +9,75 @@
|
||||||
Stylus.IsPressAndHoldEnabled="False">
|
Stylus.IsPressAndHoldEnabled="False">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<map:TileLayerCollection x:Key="TileLayers">
|
<map:TileLayerCollection x:Key="TileLayers">
|
||||||
<map:TileLayer SourceName="OpenStreetMap" Description="© {y} OpenStreetMap Contributors, CC-BY-SA"
|
<!--
|
||||||
TileSource="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
TileLayers with OpenStreetMap data.
|
||||||
<map:TileLayer SourceName="OpenCycleMap" Description="OpenCycleMap - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
-->
|
||||||
TileSource="http://{c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"/>
|
<map:TileLayer SourceName="OpenStreetMap"
|
||||||
<map:TileLayer SourceName="OCM Transport" Description="OpenCycleMap Transport - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
Description="Maps © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
TileSource="http://{c}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png"/>
|
TileSource="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
<map:TileLayer SourceName="OCM Landscape" Description="OpenCycleMap Landscape - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
MaxZoomLevel="19"/>
|
||||||
TileSource="http://{c}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png"/>
|
<map:TileLayer SourceName="Thunderforest OpenCycleMap"
|
||||||
<map:TileLayer SourceName="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors"
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
TileSource="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
TileSource="http://{c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png"/>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Landscape"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png"/>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Outdoors"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png"/>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Transport"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png"/>
|
||||||
|
<map:TileLayer SourceName="Thunderforest Transport Dark"
|
||||||
|
Description="Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://{c}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png"
|
||||||
|
Background="Black" Foreground="White"/>
|
||||||
|
<map:TileLayer SourceName="MapQuest OpenStreetMap"
|
||||||
|
Description="Maps © [MapQuest](http://www.mapquest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
|
TileSource="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"
|
||||||
|
MaxZoomLevel="19"/>
|
||||||
|
<map:TileLayer SourceName="Seamarks"
|
||||||
|
TileSource="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"
|
||||||
|
MinZoomLevel="10" MaxZoomLevel="18"/>
|
||||||
|
|
||||||
<!-- Tiles from WORLD OSM WMS, a Web Map Service based on OpenStreetMap data -->
|
<!--
|
||||||
<!--<map:TileLayer SourceName="WORLD OSM WMS" Description="WORLD OSM WMS (http://wiki.openstreetmap.org/wiki/OSM-WMS-EUROPE)"
|
Bing Maps TileLayers with tile URLs retrieved from the Imagery Metadata Service
|
||||||
|
(see http://msdn.microsoft.com/en-us/library/ff701716.aspx).
|
||||||
|
A Bing Maps API Key (see http://msdn.microsoft.com/en-us/library/ff428642.aspx) is required
|
||||||
|
for using these layers and must be assigned to the static BingMapsTileLayer.ApiKey property.
|
||||||
|
-->
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Road"
|
||||||
|
Description="© [Microsoft Corporation](http://www.bing.com/maps/)"
|
||||||
|
Mode="Road" MaxZoomLevel="19"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Aerial"
|
||||||
|
Description="© [Microsoft Corporation](http://www.bing.com/maps/)"
|
||||||
|
Mode="Aerial" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
|
<map:BingMapsTileLayer SourceName="Bing Maps Hybrid"
|
||||||
|
Description="© [Microsoft Corporation](http://www.bing.com/maps/)"
|
||||||
|
Mode="AerialWithLabels" MaxZoomLevel="19" Foreground="White" Background="Black"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
A TileLayer for World OSM WMS, a Web Map Service based on OpenStreetMap data.
|
||||||
|
-->
|
||||||
|
<!--<map:TileLayer SourceName="World OSM WMS"
|
||||||
|
Description="[World OSM WMS](http://www.osm-wms.de/) © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
TileSource="http://129.206.228.72/cached/osm?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=osm_auto:all&STYLES=&SRS=EPSG:900913&BBOX={W},{S},{E},{N}&WIDTH=256&HEIGHT=256&FORMAT=image/png"/>-->
|
TileSource="http://129.206.228.72/cached/osm?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=osm_auto:all&STYLES=&SRS=EPSG:900913&BBOX={W},{S},{E},{N}&WIDTH=256&HEIGHT=256&FORMAT=image/png"/>-->
|
||||||
|
|
||||||
<!-- Note: The providers of the following TileLayers do not allow access to their
|
<!--
|
||||||
map content without using their APIs (i.e. Google Maps API or Bing Maps API).
|
A TileLayer that uses an ImageTileSource, which bypasses caching of map tile images
|
||||||
Hence the declarations shown below are for demonstration purpose only. -->
|
-->
|
||||||
|
<!--<map:TileLayer SourceName="OSM Uncached"
|
||||||
<!--<map:TileLayer SourceName="Google Maps" Description="Google Maps - © {y} Google"
|
Description="© [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)">
|
||||||
TileSource="http://mt{i}.google.com/vt/x={x}&y={y}&z={z}" MaxZoomLevel="20"/>
|
|
||||||
<map:TileLayer SourceName="Google Images" Description="Google Maps - © {y} Google" Background="#FF3F3F3F" Foreground="White"
|
|
||||||
TileSource="http://khm{i}.google.com/kh/v=144&x={x}&y={y}&z={z}" MaxZoomLevel="20"/>
|
|
||||||
<map:TileLayer SourceName="Bing Maps" Description="Bing Maps - © {y} Microsoft Corporation"
|
|
||||||
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/r{q}.png?g=0&stl=h" MinZoomLevel="1" MaxZoomLevel="19"/>
|
|
||||||
<map:TileLayer SourceName="Bing Images" Description="Bing Maps - © {y} Microsoft Corporation" Background="#FF3F3F3F" Foreground="White"
|
|
||||||
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/a{q}.jpeg?g=0" MinZoomLevel="1" MaxZoomLevel="19"/>
|
|
||||||
<map:TileLayer SourceName="Bing Hybrid" Description="Bing Maps - © {y} Microsoft Corporation" Background="#FF3F3F3F" Foreground="White"
|
|
||||||
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/h{q}.jpeg?g=0&stl=h" MinZoomLevel="1" MaxZoomLevel="19"/>-->
|
|
||||||
|
|
||||||
<!-- The following TileLayer uses an ImageTileSource, which bypasses caching of map tile images -->
|
|
||||||
<!--<map:TileLayer SourceName="OSM Uncached" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
|
|
||||||
<map:ImageTileSource IsAsync="True" UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
<map:ImageTileSource IsAsync="True" UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||||
</map:TileLayer>-->
|
</map:TileLayer>-->
|
||||||
|
|
||||||
<!-- The following TileLayer demonstrates how to access local tile image files (from ImageFileCache here) -->
|
<!--
|
||||||
<!--<map:TileLayer SourceName="OSM Local Files" Description="© {y} OpenStreetMap Contributors, CC-BY-SA"
|
A TileLayer that demonstrates how to access local tile image files (from ImageFileCache here)
|
||||||
|
-->
|
||||||
|
<!--<map:TileLayer SourceName="OSM Local Files"
|
||||||
|
Description="© [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)"
|
||||||
TileSource="file:///C:/ProgramData/MapControl/TileCache/OpenStreetMap/{z}/{x}/{y}.png"/>-->
|
TileSource="file:///C:/ProgramData/MapControl/TileCache/OpenStreetMap/{z}/{x}/{y}.png"/>-->
|
||||||
</map:TileLayerCollection>
|
</map:TileLayerCollection>
|
||||||
<map:TileLayer x:Key="SeamarksTileLayer" SourceName="Seamarks" Description="© {y} OpenSeaMap Contributors, CC-BY-SA"
|
|
||||||
TileSource="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png" MinZoomLevel="10" MaxZoomLevel="18"/>
|
|
||||||
<CollectionViewSource x:Key="TileLayersViewSource" Source="{StaticResource TileLayers}"/>
|
|
||||||
<local:LocationToVisibilityConverter x:Key="LocationToVisibilityConverter"/>
|
<local:LocationToVisibilityConverter x:Key="LocationToVisibilityConverter"/>
|
||||||
<DataTemplate x:Key="PolylineItemTemplate">
|
<DataTemplate x:Key="PolylineItemTemplate">
|
||||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||||
|
|
@ -66,6 +93,7 @@
|
||||||
</Style>
|
</Style>
|
||||||
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
||||||
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
|
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
|
||||||
|
<Setter Property="Foreground" Value="Black"/>
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate TargetType="map:MapItem">
|
<ControlTemplate TargetType="map:MapItem">
|
||||||
|
|
@ -146,23 +174,22 @@
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<map:Map x:Name="map" Margin="2" Center="{Binding MapCenter}" ZoomLevel="11" MaxZoomLevel="20"
|
<map:Map x:Name="map" Center="{Binding MapCenter}" ZoomLevel="11" MaxZoomLevel="20"
|
||||||
TileLayer="{Binding Source={StaticResource TileLayersViewSource}, Path=CurrentItem}"
|
|
||||||
MouseLeftButtonDown="MapMouseLeftButtonDown" MouseRightButtonDown="MapMouseRightButtonDown"
|
MouseLeftButtonDown="MapMouseLeftButtonDown" MouseRightButtonDown="MapMouseRightButtonDown"
|
||||||
MouseMove="MapMouseMove" MouseLeave="MapMouseLeave"
|
MouseMove="MapMouseMove" MouseLeave="MapMouseLeave"
|
||||||
ManipulationInertiaStarting="MapManipulationInertiaStarting">
|
ManipulationInertiaStarting="MapManipulationInertiaStarting">
|
||||||
|
|
||||||
<!-- experimental WMS map layers -->
|
<!-- experimental WMS map layers -->
|
||||||
<!--<map:MapImageLayer Opacity="0.5"
|
<!--<map:MapImageLayer
|
||||||
UriFormat="http://watzmann-geog.urz.uni-heidelberg.de/cached/osm?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=osm_auto:all&STYLES=&SRS=EPSG:900913&BBOX={W},{S},{E},{N}&WIDTH={X}&HEIGHT={Y}&FORMAT=image/png"/>-->
|
UriFormat="http://129.206.228.72/cached/osm?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=osm_auto:all&STYLES=&SRS=EPSG:900913&BBOX={W},{S},{E},{N}&WIDTH={X}&HEIGHT={Y}&FORMAT=image/png"/>-->
|
||||||
<!--<map:MapImageLayer Opacity="0.5"
|
<!--<map:MapImageLayer
|
||||||
UriFormat="http://ows.terrestris.de/osm/service?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=OSM-WMS&STYLES=&SRS=EPSG:900913&BBOX={W},{S},{E},{N}&WIDTH={X}&HEIGHT={Y}&FORMAT=image/png"/>-->
|
UriFormat="http://ows.terrestris.de/osm/service?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=OSM-WMS&STYLES=&SRS=EPSG:900913&BBOX={W},{S},{E},{N}&WIDTH={X}&HEIGHT={Y}&FORMAT=image/png"/>-->
|
||||||
|
|
||||||
<map:MapImage x:Name="mapImage" South="53.54031" North="53.74871" West="8.08594" East="8.43750"
|
<map:MapImage x:Name="mapImage" South="53.54031" North="53.74871" West="8.08594" East="8.43750"
|
||||||
Source="10_535_330.jpg" Opacity="0.5"/>
|
Source="10_535_330.jpg" Opacity="0.5"/>
|
||||||
|
|
||||||
<map:MapGraticule Opacity="0.6"/>
|
<map:MapGraticule Opacity="0.6"/>
|
||||||
<map:MapScale Margin="4" Opacity="0.8"/>
|
<map:MapScale Margin="4" Opacity="0.8" HorizontalAlignment="Left"/>
|
||||||
|
|
||||||
<!-- use ItemTemplate or ItemContainerStyle alternatively -->
|
<!-- use ItemTemplate or ItemContainerStyle alternatively -->
|
||||||
<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
||||||
|
|
@ -193,10 +220,10 @@
|
||||||
<EllipseGeometry RadiusX="1852" RadiusY="1852" Transform="{Binding ScaleTransform, ElementName=map}"/>
|
<EllipseGeometry RadiusX="1852" RadiusY="1852" Transform="{Binding ScaleTransform, ElementName=map}"/>
|
||||||
</Path.Data>
|
</Path.Data>
|
||||||
</Path>
|
</Path>
|
||||||
|
|
||||||
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="4" FontSize="10"
|
|
||||||
Text="{Binding TileLayer.Description, ElementName=map}"/>
|
|
||||||
</map:Map>
|
</map:Map>
|
||||||
|
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#7FFFFFFF">
|
||||||
|
<TextBlock x:Name="mapLegend" Margin="2" FontSize="10"/>
|
||||||
|
</Border>
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
|
|
@ -223,8 +250,19 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<CheckBox ToolTip="Seamarks Overlay" Margin="7" VerticalAlignment="Bottom" Content="Seamarks"
|
<CheckBox ToolTip="Seamarks Overlay" Margin="7" VerticalAlignment="Bottom" Content="Seamarks"
|
||||||
Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
||||||
<ComboBox ToolTip="Tile Layer" Margin="5" VerticalAlignment="Bottom" DisplayMemberPath="SourceName"
|
<ComboBox x:Name="tileLayerComboBox" ToolTip="Tile Layer" Margin="5" VerticalAlignment="Bottom"
|
||||||
SelectedIndex="0" ItemsSource="{Binding Source={StaticResource TileLayersViewSource}}"/>
|
SelectionChanged="TileLayerSelectionChanged">
|
||||||
|
<ComboBoxItem Tag="OpenStreetMap">OpenStreetMap</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest OpenCycleMap">OpenCycleMap</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest Landscape">Landscape</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest Outdoors">Outdoors</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest Transport">Transport</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Thunderforest Transport Dark">Transport Dark</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="MapQuest OpenStreetMap">MapQuest Open</ComboBoxItem>
|
||||||
|
<!--<ComboBoxItem Tag="Bing Maps Road">Bing Maps Road</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Bing Maps Aerial">Bing Maps Aerial</ComboBoxItem>
|
||||||
|
<ComboBoxItem Tag="Bing Maps Hybrid">Bing Maps Hybrid</ComboBoxItem>-->
|
||||||
|
</ComboBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Runtime.Caching;
|
using System.Runtime.Caching;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Caching;
|
using Caching;
|
||||||
using MapControl;
|
using MapControl;
|
||||||
|
|
@ -10,24 +11,34 @@ namespace WpfApplication
|
||||||
{
|
{
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
|
private TileLayerCollection tileLayers;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
switch (Properties.Settings.Default.TileCache)
|
switch (Properties.Settings.Default.TileCache)
|
||||||
{
|
{
|
||||||
case "MemoryCache":
|
case "MemoryCache":
|
||||||
TileImageLoader.Cache = MemoryCache.Default;
|
TileImageLoader.Cache = MemoryCache.Default; // this is the default value of the TileImageLoader.Cache property
|
||||||
|
break;
|
||||||
|
case "ImageFileCache":
|
||||||
|
TileImageLoader.Cache = new ImageFileCache(TileImageLoader.DefaultCacheName, TileImageLoader.DefaultCacheDirectory);
|
||||||
break;
|
break;
|
||||||
case "FileDbCache":
|
case "FileDbCache":
|
||||||
TileImageLoader.Cache = new FileDbCache(TileImageLoader.DefaultCacheName, TileImageLoader.DefaultCacheDirectory);
|
TileImageLoader.Cache = new FileDbCache(TileImageLoader.DefaultCacheName, TileImageLoader.DefaultCacheDirectory);
|
||||||
break;
|
break;
|
||||||
case "ImageFileCache":
|
case "None":
|
||||||
TileImageLoader.Cache = new ImageFileCache(TileImageLoader.DefaultCacheName, TileImageLoader.DefaultCacheDirectory);
|
TileImageLoader.Cache = null;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//BingMapsTileLayer.ApiKey = ...
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||||
|
tileLayerComboBox.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
private void MapMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
|
|
@ -90,14 +101,24 @@ namespace WpfApplication
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TileLayerSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var selectedItem = (ComboBoxItem)tileLayerComboBox.SelectedItem;
|
||||||
|
|
||||||
|
map.TileLayer = tileLayers[(string)selectedItem.Tag];
|
||||||
|
|
||||||
|
mapLegend.Inlines.Clear();
|
||||||
|
mapLegend.Inlines.AddRange(map.TileLayer.DescriptionInlines);
|
||||||
|
}
|
||||||
|
|
||||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
map.TileLayers.Add((TileLayer)Resources["SeamarksTileLayer"]);
|
map.TileLayers.Add(tileLayers["Seamarks"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
map.TileLayers.Remove((TileLayer)Resources["SeamarksTileLayer"]);
|
map.TileLayers.Remove(tileLayers["Seamarks"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyVersion("2.2.0")]
|
[assembly: AssemblyVersion("2.3.0")]
|
||||||
[assembly: AssemblyFileVersion("2.2.0")]
|
[assembly: AssemblyFileVersion("2.3.0")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue