mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Reworked sample applications
This commit is contained in:
parent
9ce981a6ee
commit
32491a8e31
|
|
@ -67,7 +67,7 @@ namespace MapControl
|
|||
|
||||
if (values.Length != 4)
|
||||
{
|
||||
throw new FormatException("BoundingBox string must be a comma-separated list of four double values.");
|
||||
throw new FormatException("BoundingBox string must be a comma-separated list of four floating point numbers.");
|
||||
}
|
||||
|
||||
return new BoundingBox(
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBTiles.WinUI", "MBTiles\Wi
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUiApp", "SampleApps\WinUiApp\WinUiApp.csproj", "{751EF297-7CF4-4879-BA8F-42661FA68668}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectionDemo", "SampleApps\ProjectionDemo\ProjectionDemo.csproj", "{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -428,6 +430,22 @@ Global
|
|||
{751EF297-7CF4-4879-BA8F-42661FA68668}.Release|x86.ActiveCfg = Release|x86
|
||||
{751EF297-7CF4-4879-BA8F-42661FA68668}.Release|x86.Build.0 = Release|x86
|
||||
{751EF297-7CF4-4879-BA8F-42661FA68668}.Release|x86.Deploy.0 = Release|x86
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|arm64.ActiveCfg = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|arm64.Build.0 = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|arm64.ActiveCfg = Release|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|arm64.Build.0 = Release|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -454,6 +472,7 @@ Global
|
|||
{1F9FBADF-65C0-453D-9B45-7A88044F807F} = {2FDC8B91-FB95-4C57-8183-63587FBFE180}
|
||||
{817D606F-A22D-485C-89CF-86062C8E97EF} = {CEAD0EA1-A971-4F5F-9EAE-C72F75D1F737}
|
||||
{751EF297-7CF4-4879-BA8F-42661FA68668} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
|
||||
{AC8C7BE0-9E72-434B-8BF3-FAEFAC2E859C} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {458346DD-B23F-4FDC-8F9D-A10F1882A4DB}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.ComponentModel;
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@
|
|||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Version>6.1.0</Version>
|
||||
<Version>7.0.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Description>XAML Map Control Map Projection Demo Application</Description>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Copyright>Copyright © 2020 Clemens Fischer</Copyright>
|
||||
<Copyright>Copyright © 2021 Clemens Fischer</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,182 +0,0 @@
|
|||
using MapControl;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
#if WINUI
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#elif UWP
|
||||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace SampleApplication
|
||||
{
|
||||
public class MapLayers : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
// See https://wiki.openstreetmap.org/wiki/Tile_servers for a list of free OpenStreetMap Tile Servers
|
||||
|
||||
private readonly Dictionary<string, UIElement> mapLayers = new Dictionary<string, UIElement>
|
||||
{
|
||||
{
|
||||
"OpenStreetMap",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "https://tile.openstreetmap.org/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenStreetMap",
|
||||
Description = "© [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenStreetMap German",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenStreetMap German",
|
||||
Description = "© [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenStreetMap French",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenStreetMap French",
|
||||
Description = "© [OpenStreetMap France](https://www.openstreetmap.fr/mentions-legales/) © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenTopoMap",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "https://tile.opentopomap.org/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenTopoMap",
|
||||
Description = "© [OpenTopoMap](https://opentopomap.org/) © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)",
|
||||
MaxZoomLevel = 17
|
||||
}
|
||||
},
|
||||
{
|
||||
"Seamarks",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenSeaMap",
|
||||
MinZoomLevel = 9,
|
||||
MaxZoomLevel = 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"Bing Maps Road",
|
||||
new BingMapsTileLayer
|
||||
{
|
||||
Mode = BingMapsTileLayer.MapMode.Road,
|
||||
SourceName = "Bing Maps Road",
|
||||
Description = "© [Microsoft](http://www.bing.com/maps/)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Bing Maps Aerial",
|
||||
new BingMapsTileLayer
|
||||
{
|
||||
Mode = BingMapsTileLayer.MapMode.Aerial,
|
||||
SourceName = "Bing Maps Aerial",
|
||||
Description = "© [Microsoft](http://www.bing.com/maps/)",
|
||||
MapForeground = new SolidColorBrush(Colors.White),
|
||||
MapBackground = new SolidColorBrush(Colors.Black)
|
||||
}
|
||||
},
|
||||
{
|
||||
"Bing Maps Aerial with Labels",
|
||||
new BingMapsTileLayer
|
||||
{
|
||||
Mode = BingMapsTileLayer.MapMode.AerialWithLabels,
|
||||
SourceName = "Bing Maps Hybrid",
|
||||
Description = "© [Microsoft](http://www.bing.com/maps/)",
|
||||
MapForeground = new SolidColorBrush(Colors.White),
|
||||
MapBackground = new SolidColorBrush(Colors.Black)
|
||||
}
|
||||
},
|
||||
{
|
||||
"TopPlusOpen WMTS",
|
||||
new WmtsTileLayer
|
||||
{
|
||||
SourceName = "TopPlusOpen",
|
||||
Description = "© [BKG](https://gdz.bkg.bund.de/index.php/default/webdienste/topplus-produkte/wmts-topplusopen-wmts-topplus-open.html)",
|
||||
CapabilitiesUri = new Uri("https://sgx.geodatenzentrum.de/wmts_topplus_open/1.0.0/WMTSCapabilities.xml")
|
||||
}
|
||||
},
|
||||
{
|
||||
"TopPlusOpen WMS",
|
||||
new WmsImageLayer
|
||||
{
|
||||
Description = "© [BKG](https://gdz.bkg.bund.de/index.php/default/webdienste/topplus-produkte/wms-topplusopen-mit-layer-fur-normalausgabe-und-druck-wms-topplus-open.html)",
|
||||
ServiceUri = new Uri("https://sgx.geodatenzentrum.de/wms_topplus_open")
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenStreetMap WMS",
|
||||
new WmsImageLayer
|
||||
{
|
||||
Description = "© [terrestris GmbH & Co. KG](http://ows.terrestris.de/) © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)",
|
||||
ServiceUri = new Uri("http://ows.terrestris.de/osm/service")
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
private string currentMapLayerName = "OpenStreetMap";
|
||||
|
||||
public string CurrentMapLayerName
|
||||
{
|
||||
get { return currentMapLayerName; }
|
||||
set
|
||||
{
|
||||
currentMapLayerName = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentMapLayerName)));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentMapLayer)));
|
||||
}
|
||||
}
|
||||
|
||||
public UIElement CurrentMapLayer
|
||||
{
|
||||
get { return mapLayers[currentMapLayerName]; }
|
||||
}
|
||||
|
||||
public UIElement SeamarksLayer
|
||||
{
|
||||
get { return mapLayers["Seamarks"]; }
|
||||
}
|
||||
|
||||
public List<string> MapLayerNames { get; } = new List<string>
|
||||
{
|
||||
"OpenStreetMap",
|
||||
"OpenStreetMap German",
|
||||
"OpenStreetMap French",
|
||||
"OpenTopoMap",
|
||||
"TopPlusOpen WMTS",
|
||||
"TopPlusOpen WMS",
|
||||
"OpenStreetMap WMS",
|
||||
};
|
||||
|
||||
public MapLayers()
|
||||
{
|
||||
// Add Bing Maps TileLayers with tile URLs retrieved from the Imagery Metadata Service
|
||||
// (http://msdn.microsoft.com/en-us/library/ff701716.aspx).
|
||||
// A Bing Maps API Key (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.
|
||||
|
||||
if (!string.IsNullOrEmpty(BingMapsTileLayer.ApiKey))
|
||||
{
|
||||
MapLayerNames.Add("Bing Maps Road");
|
||||
MapLayerNames.Add("Bing Maps Aerial");
|
||||
MapLayerNames.Add("Bing Maps Aerial with Labels");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
158
SampleApps/Shared/MapLayersMenuButton.cs
Normal file
158
SampleApps/Shared/MapLayersMenuButton.cs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
using MapControl;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace SampleApplication
|
||||
{
|
||||
public class MapLayersMenuButton : MenuButton
|
||||
{
|
||||
public MapLayersMenuButton()
|
||||
{
|
||||
#if WINUI || UWP
|
||||
Content = new FontIcon
|
||||
{
|
||||
FontFamily = new FontFamily("Segoe MDL2 Assets"),
|
||||
Glyph = "\uE81E"
|
||||
};
|
||||
#else
|
||||
FontFamily = new FontFamily("Segoe MDL2 Assets");
|
||||
Content = "\uE81E";
|
||||
#endif
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MapProperty = DependencyProperty.Register(
|
||||
nameof(Map), typeof(MapBase), typeof(MapLayersMenuButton),
|
||||
new PropertyMetadata(null, (o, e) => ((MapLayersMenuButton)o).InitializeMenu()));
|
||||
|
||||
public static readonly DependencyProperty MapLayersProperty = DependencyProperty.Register(
|
||||
nameof(MapLayers), typeof(IDictionary<string, UIElement>), typeof(MapLayersMenuButton),
|
||||
new PropertyMetadata(null, (o, e) => ((MapLayersMenuButton)o).InitializeMenu()));
|
||||
|
||||
public static readonly DependencyProperty MapOverlaysProperty = DependencyProperty.Register(
|
||||
nameof(MapOverlays), typeof(IDictionary<string, UIElement>), typeof(MapLayersMenuButton),
|
||||
new PropertyMetadata(null, (o, e) => ((MapLayersMenuButton)o).InitializeMenu()));
|
||||
|
||||
public MapBase Map
|
||||
{
|
||||
get { return (MapBase)GetValue(MapProperty); }
|
||||
set { SetValue(MapProperty, value); }
|
||||
}
|
||||
|
||||
public IDictionary<string, UIElement> MapLayers
|
||||
{
|
||||
get { return (IDictionary<string, UIElement>)GetValue(MapLayersProperty); }
|
||||
set { SetValue(MapLayersProperty, value); }
|
||||
}
|
||||
|
||||
public IDictionary<string, UIElement> MapOverlays
|
||||
{
|
||||
get { return (IDictionary<string, UIElement>)GetValue(MapOverlaysProperty); }
|
||||
set { SetValue(MapOverlaysProperty, value); }
|
||||
}
|
||||
|
||||
private void InitializeMenu()
|
||||
{
|
||||
if (Map != null && MapLayers != null)
|
||||
{
|
||||
var menu = CreateMenu();
|
||||
|
||||
foreach (var layer in MapLayers)
|
||||
{
|
||||
menu.Items.Add(CreateMenuItem(layer.Key, layer.Value, MapLayerClicked));
|
||||
}
|
||||
|
||||
var initialLayer = MapLayers.Values.FirstOrDefault();
|
||||
|
||||
if (MapOverlays != null && MapOverlays.Any())
|
||||
{
|
||||
if (initialLayer != null)
|
||||
{
|
||||
menu.Items.Add(CreateSeparator());
|
||||
}
|
||||
|
||||
foreach (var overlay in MapOverlays)
|
||||
{
|
||||
menu.Items.Add(CreateMenuItem(overlay.Key, overlay.Value, MapOverlayClicked));
|
||||
}
|
||||
}
|
||||
|
||||
if (initialLayer != null)
|
||||
{
|
||||
SetMapLayer(initialLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MapLayerClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = (FrameworkElement)sender;
|
||||
var layer = (UIElement)item.Tag;
|
||||
|
||||
SetMapLayer(layer);
|
||||
}
|
||||
|
||||
private void MapOverlayClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = (FrameworkElement)sender;
|
||||
var layer = (UIElement)item.Tag;
|
||||
|
||||
ToggleMapOverlay(layer);
|
||||
}
|
||||
|
||||
private void SetMapLayer(UIElement layer)
|
||||
{
|
||||
Map.MapLayer = layer;
|
||||
|
||||
UpdateCheckedStates();
|
||||
}
|
||||
|
||||
private void ToggleMapOverlay(UIElement layer)
|
||||
{
|
||||
if (Map.Children.Contains(layer))
|
||||
{
|
||||
Map.Children.Remove(layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = 1;
|
||||
|
||||
foreach (var overlay in MapOverlays.Values)
|
||||
{
|
||||
if (overlay == layer)
|
||||
{
|
||||
Map.Children.Insert(index, layer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Map.Children.Contains(overlay))
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCheckedStates();
|
||||
}
|
||||
|
||||
private void UpdateCheckedStates()
|
||||
{
|
||||
foreach (var item in GetMenuItems())
|
||||
{
|
||||
item.IsChecked = Map.Children.Contains((UIElement)item.Tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
94
SampleApps/Shared/MapProjectionsMenuButton.cs
Normal file
94
SampleApps/Shared/MapProjectionsMenuButton.cs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
using MapControl;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace SampleApplication
|
||||
{
|
||||
public class MapProjectionsMenuButton : MenuButton
|
||||
{
|
||||
public MapProjectionsMenuButton()
|
||||
{
|
||||
#if WINUI || UWP
|
||||
Content = new FontIcon
|
||||
{
|
||||
FontFamily = new FontFamily("Segoe MDL2 Assets"),
|
||||
Glyph = "\uE809"
|
||||
};
|
||||
#else
|
||||
FontFamily = new FontFamily("Segoe MDL2 Assets");
|
||||
Content = "\uE809";
|
||||
#endif
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MapProperty = DependencyProperty.Register(
|
||||
nameof(Map), typeof(MapBase), typeof(MapProjectionsMenuButton),
|
||||
new PropertyMetadata(null, (o, e) => ((MapProjectionsMenuButton)o).InitializeMenu()));
|
||||
|
||||
public static readonly DependencyProperty MapProjectionsProperty = DependencyProperty.Register(
|
||||
nameof(MapProjections), typeof(IDictionary<string, MapProjection>), typeof(MapProjectionsMenuButton),
|
||||
new PropertyMetadata(null, (o, e) => ((MapProjectionsMenuButton)o).InitializeMenu()));
|
||||
|
||||
public MapBase Map
|
||||
{
|
||||
get { return (MapBase)GetValue(MapProperty); }
|
||||
set { SetValue(MapProperty, value); }
|
||||
}
|
||||
|
||||
public IDictionary<string, MapProjection> MapProjections
|
||||
{
|
||||
get { return (IDictionary<string, MapProjection>)GetValue(MapProjectionsProperty); }
|
||||
set { SetValue(MapProjectionsProperty, value); }
|
||||
}
|
||||
|
||||
private void InitializeMenu()
|
||||
{
|
||||
if (Map != null && MapProjections != null)
|
||||
{
|
||||
var menu = CreateMenu();
|
||||
|
||||
foreach (var projection in MapProjections)
|
||||
{
|
||||
menu.Items.Add(CreateMenuItem(projection.Key, projection.Value, MapProjectionClicked));
|
||||
}
|
||||
|
||||
var initialProjection = MapProjections.Values.FirstOrDefault();
|
||||
|
||||
if (initialProjection != null)
|
||||
{
|
||||
SetMapProjection(initialProjection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MapProjectionClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = (FrameworkElement)sender;
|
||||
var projection = (MapProjection)item.Tag;
|
||||
|
||||
SetMapProjection(projection);
|
||||
}
|
||||
|
||||
private void SetMapProjection(MapProjection projection)
|
||||
{
|
||||
Map.MapProjection = projection;
|
||||
|
||||
foreach (var item in GetMenuItems())
|
||||
{
|
||||
item.IsChecked = Map.MapProjection == (MapProjection)item.Tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,95 +1,233 @@
|
|||
using MapControl;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if WINUI
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
#elif UWP
|
||||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace SampleApplication
|
||||
{
|
||||
public class ViewModelBase : INotifyPropertyChanged
|
||||
public class PointItem
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public string Name { get; set; }
|
||||
|
||||
protected void RaisePropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
public Location Location { get; set; }
|
||||
}
|
||||
|
||||
public class PointItem : ViewModelBase
|
||||
{
|
||||
private string name;
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set
|
||||
{
|
||||
name = value;
|
||||
RaisePropertyChanged(nameof(Name));
|
||||
}
|
||||
}
|
||||
|
||||
private Location location;
|
||||
public Location Location
|
||||
{
|
||||
get { return location; }
|
||||
set
|
||||
{
|
||||
location = value;
|
||||
RaisePropertyChanged(nameof(Location));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Polyline
|
||||
public class PolylineItem
|
||||
{
|
||||
public LocationCollection Locations { get; set; }
|
||||
}
|
||||
|
||||
public class MapViewModel : ViewModelBase
|
||||
public class MapViewModel
|
||||
{
|
||||
private Location mapCenter = new Location(53.5, 8.2);
|
||||
public Location MapCenter
|
||||
public List<PointItem> Points { get; } = new List<PointItem>();
|
||||
public List<PointItem> Pushpins { get; } = new List<PointItem>();
|
||||
public List<PolylineItem> Polylines { get; } = new List<PolylineItem>();
|
||||
|
||||
public Dictionary<string, MapProjection> MapProjections { get; } = new Dictionary<string, MapProjection>
|
||||
{
|
||||
{ "Web Mercator", new WebMercatorProjection() },
|
||||
{ "World Mercator", new WorldMercatorProjection() },
|
||||
{ "Equirectangular", new EquirectangularProjection() },
|
||||
{ "Orthographic", new OrthographicProjection() },
|
||||
{ "Gnomonic", new GnomonicProjection() },
|
||||
{ "Stereographic", new StereographicProjection() }
|
||||
};
|
||||
|
||||
public Dictionary<string, UIElement> MapLayers { get; } = new Dictionary<string, UIElement>
|
||||
{
|
||||
get { return mapCenter; }
|
||||
set
|
||||
{
|
||||
mapCenter = value;
|
||||
RaisePropertyChanged(nameof(MapCenter));
|
||||
"OpenStreetMap",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "https://tile.openstreetmap.org/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenStreetMap",
|
||||
Description = "© [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenStreetMap German",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenStreetMap German",
|
||||
Description = "© [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenStreetMap French",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenStreetMap French",
|
||||
Description = "© [OpenStreetMap France](https://www.openstreetmap.fr/mentions-legales/) © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenTopoMap",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "https://tile.opentopomap.org/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenTopoMap",
|
||||
Description = "© [OpenTopoMap](https://opentopomap.org/) © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)",
|
||||
MaxZoomLevel = 17
|
||||
}
|
||||
},
|
||||
{
|
||||
"TopPlusOpen WMTS",
|
||||
new WmtsTileLayer
|
||||
{
|
||||
SourceName = "TopPlusOpen",
|
||||
Description = "© [BKG](https://gdz.bkg.bund.de/index.php/default/webdienste/topplus-produkte/wmts-topplusopen-wmts-topplus-open.html)",
|
||||
CapabilitiesUri = new Uri("https://sgx.geodatenzentrum.de/wmts_topplus_open/1.0.0/WMTSCapabilities.xml")
|
||||
}
|
||||
},
|
||||
{
|
||||
"TopPlusOpen WMS",
|
||||
new WmsImageLayer
|
||||
{
|
||||
Description = "© [BKG](https://gdz.bkg.bund.de/index.php/default/webdienste/topplus-produkte/wms-topplusopen-mit-layer-fur-normalausgabe-und-druck-wms-topplus-open.html)",
|
||||
ServiceUri = new Uri("https://sgx.geodatenzentrum.de/wms_topplus_open")
|
||||
}
|
||||
},
|
||||
{
|
||||
"OpenStreetMap WMS",
|
||||
new WmsImageLayer
|
||||
{
|
||||
Description = "© [terrestris GmbH & Co. KG](http://ows.terrestris.de/) © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)",
|
||||
ServiceUri = new Uri("http://ows.terrestris.de/osm/service")
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ObservableCollection<PointItem> Points { get; } = new ObservableCollection<PointItem>();
|
||||
public ObservableCollection<PointItem> Pushpins { get; } = new ObservableCollection<PointItem>();
|
||||
public ObservableCollection<Polyline> Polylines { get; } = new ObservableCollection<Polyline>();
|
||||
|
||||
public MapLayers MapLayers { get; } = new MapLayers();
|
||||
public Dictionary<string, UIElement> MapOverlays { get; } = new Dictionary<string, UIElement>
|
||||
{
|
||||
{
|
||||
"Sample Image",
|
||||
new Image()
|
||||
},
|
||||
{
|
||||
"Seamarks",
|
||||
new MapTileLayer
|
||||
{
|
||||
TileSource = new TileSource { UriFormat = "http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png" },
|
||||
SourceName = "OpenSeaMap",
|
||||
MinZoomLevel = 9,
|
||||
MaxZoomLevel = 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"Graticule",
|
||||
new MapGraticule
|
||||
{
|
||||
Opacity = 0.75
|
||||
}
|
||||
},
|
||||
{
|
||||
"Scale",
|
||||
new MapScale
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Bottom
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public MapViewModel()
|
||||
{
|
||||
// Add Bing Maps TileLayers with tile URLs retrieved from the Imagery Metadata Service
|
||||
// (http://msdn.microsoft.com/en-us/library/ff701716.aspx).
|
||||
// A Bing Maps API Key (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.
|
||||
|
||||
if (!string.IsNullOrEmpty(BingMapsTileLayer.ApiKey))
|
||||
{
|
||||
MapLayers.Add(
|
||||
"Bing Maps Road",
|
||||
new BingMapsTileLayer
|
||||
{
|
||||
Mode = BingMapsTileLayer.MapMode.Road,
|
||||
SourceName = "Bing Maps Road",
|
||||
Description = "© [Microsoft](http://www.bing.com/maps/)"
|
||||
});
|
||||
|
||||
MapLayers.Add(
|
||||
"Bing Maps Aerial",
|
||||
new BingMapsTileLayer
|
||||
{
|
||||
Mode = BingMapsTileLayer.MapMode.Aerial,
|
||||
SourceName = "Bing Maps Aerial",
|
||||
Description = "© [Microsoft](http://www.bing.com/maps/)",
|
||||
MapForeground = new SolidColorBrush(Colors.White),
|
||||
MapBackground = new SolidColorBrush(Colors.Black)
|
||||
});
|
||||
|
||||
MapLayers.Add(
|
||||
"Bing Maps Aerial with Labels",
|
||||
new BingMapsTileLayer
|
||||
{
|
||||
Mode = BingMapsTileLayer.MapMode.AerialWithLabels,
|
||||
SourceName = "Bing Maps Hybrid",
|
||||
Description = "© [Microsoft](http://www.bing.com/maps/)",
|
||||
MapForeground = new SolidColorBrush(Colors.White),
|
||||
MapBackground = new SolidColorBrush(Colors.Black)
|
||||
});
|
||||
}
|
||||
|
||||
var sampleImage = (Image)MapOverlays["Sample Image"];
|
||||
#if WINUI || UWP
|
||||
sampleImage.Source = new BitmapImage(new Uri("ms-appx:///10_535_330.jpg"));
|
||||
#else
|
||||
sampleImage.Source = new BitmapImage(new Uri("pack://siteoforigin:,,,/10_535_330.jpg"));
|
||||
#endif
|
||||
MapPanel.SetBoundingBox(sampleImage, new BoundingBox(53.54031, 8.08594, 53.74871, 8.43750));
|
||||
|
||||
Points.Add(new PointItem
|
||||
{
|
||||
Name = "Steinbake Leitdamm",
|
||||
Location = new Location(53.51217, 8.16603)
|
||||
});
|
||||
|
||||
Points.Add(new PointItem
|
||||
{
|
||||
Name = "Buhne 2",
|
||||
Location = new Location(53.50926, 8.15815)
|
||||
});
|
||||
|
||||
Points.Add(new PointItem
|
||||
{
|
||||
Name = "Buhne 4",
|
||||
Location = new Location(53.50468, 8.15343)
|
||||
});
|
||||
|
||||
Points.Add(new PointItem
|
||||
{
|
||||
Name = "Buhne 6",
|
||||
Location = new Location(53.50092, 8.15267)
|
||||
});
|
||||
|
||||
Points.Add(new PointItem
|
||||
{
|
||||
Name = "Buhne 8",
|
||||
Location = new Location(53.49871, 8.15321)
|
||||
});
|
||||
|
||||
Points.Add(new PointItem
|
||||
{
|
||||
Name = "Buhne 10",
|
||||
|
|
@ -101,27 +239,31 @@ namespace SampleApplication
|
|||
Name = "WHV - Eckwarderhörne",
|
||||
Location = new Location(53.5495, 8.1877)
|
||||
});
|
||||
|
||||
Pushpins.Add(new PointItem
|
||||
{
|
||||
Name = "JadeWeserPort",
|
||||
Location = new Location(53.5914, 8.14)
|
||||
});
|
||||
|
||||
Pushpins.Add(new PointItem
|
||||
{
|
||||
Name = "Kurhaus Dangast",
|
||||
Location = new Location(53.447, 8.1114)
|
||||
});
|
||||
|
||||
Pushpins.Add(new PointItem
|
||||
{
|
||||
Name = "Eckwarderhörne",
|
||||
Location = new Location(53.5207, 8.2323)
|
||||
});
|
||||
|
||||
Polylines.Add(new Polyline
|
||||
Polylines.Add(new PolylineItem
|
||||
{
|
||||
Locations = LocationCollection.Parse("53.5140,8.1451 53.5123,8.1506 53.5156,8.1623 53.5276,8.1757 53.5491,8.1852 53.5495,8.1877 53.5426,8.1993 53.5184,8.2219 53.5182,8.2386 53.5195,8.2387")
|
||||
});
|
||||
Polylines.Add(new Polyline
|
||||
|
||||
Polylines.Add(new PolylineItem
|
||||
{
|
||||
Locations = LocationCollection.Parse("53.5978,8.1212 53.6018,8.1494 53.5859,8.1554 53.5852,8.1531 53.5841,8.1539 53.5802,8.1392 53.5826,8.1309 53.5867,8.1317 53.5978,8.1212")
|
||||
});
|
||||
|
|
|
|||
73
SampleApps/Shared/MenuButton.cs
Normal file
73
SampleApps/Shared/MenuButton.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
#endif
|
||||
|
||||
namespace SampleApplication
|
||||
{
|
||||
public class MenuButton : Button
|
||||
{
|
||||
#if WINUI || UWP
|
||||
protected MenuFlyout CreateMenu()
|
||||
{
|
||||
var menu = new MenuFlyout();
|
||||
Flyout = menu;
|
||||
return menu;
|
||||
}
|
||||
|
||||
protected IEnumerable<ToggleMenuFlyoutItem> GetMenuItems()
|
||||
{
|
||||
return ((MenuFlyout)Flyout).Items.OfType<ToggleMenuFlyoutItem>();
|
||||
}
|
||||
|
||||
protected static ToggleMenuFlyoutItem CreateMenuItem(string text, object item, RoutedEventHandler click)
|
||||
{
|
||||
var menuItem = new ToggleMenuFlyoutItem { Text = text, Tag = item };
|
||||
menuItem.Click += click;
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
protected static MenuFlyoutSeparator CreateSeparator()
|
||||
{
|
||||
return new MenuFlyoutSeparator();
|
||||
}
|
||||
#else
|
||||
protected ContextMenu CreateMenu()
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
ContextMenu = menu;
|
||||
return menu;
|
||||
}
|
||||
|
||||
protected IEnumerable<MenuItem> GetMenuItems()
|
||||
{
|
||||
return ContextMenu.Items.OfType<MenuItem>();
|
||||
}
|
||||
|
||||
protected static MenuItem CreateMenuItem(string text, object item, RoutedEventHandler click)
|
||||
{
|
||||
var menuItem = new MenuItem { Header = text, Tag = item };
|
||||
menuItem.Click += click;
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
protected static Separator CreateSeparator()
|
||||
{
|
||||
return new Separator();
|
||||
}
|
||||
|
||||
protected MenuButton()
|
||||
{
|
||||
Click += (s, e) => ContextMenu.IsOpen = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -2,129 +2,99 @@
|
|||
x:Class="SampleApplication.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:SampleApplication"
|
||||
xmlns:map="using:MapControl">
|
||||
xmlns:map="using:MapControl"
|
||||
xmlns:local="using:SampleApplication">
|
||||
|
||||
<Page.Resources>
|
||||
<DataTemplate x:Key="PolylineItemTemplate">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</DataTemplate>
|
||||
|
||||
<Style x:Key="PolylineItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="LocationMemberPath" Value="Location"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<Canvas>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Disabled"/>
|
||||
<VisualState x:Name="PointerOver"/>
|
||||
<VisualState x:Name="Pressed"/>
|
||||
<VisualState x:Name="Selected">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SelectedUnfocused">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SelectedPointerOver">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SelectedPressed">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Path x:Name="selectedPath" Fill="White" Opacity="0">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="12" RadiusY="12"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Fill="Transparent" Stroke="Gray" StrokeThickness="2">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Grid Canvas.Left="15" Canvas.Top="-8">
|
||||
<TextBlock Margin="2,0,2,0" Text="{Binding Name}"/>
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PushpinItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="LocationMemberPath" Value="Location"/>
|
||||
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<map:Pushpin Content="{Binding Name}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<map:WebMercatorProjection x:Key="WebMercatorProjection"/>
|
||||
<map:WorldMercatorProjection x:Key="WorldMercatorProjection"/>
|
||||
<map:EquirectangularProjection x:Key="EquirectangularProjection"/>
|
||||
<map:OrthographicProjection x:Key="OrthographicProjection"/>
|
||||
<map:GnomonicProjection x:Key="GnomonicProjection"/>
|
||||
<map:StereographicProjection x:Key="StereographicProjection"/>
|
||||
</Page.Resources>
|
||||
<Page.DataContext>
|
||||
<local:MapViewModel/>
|
||||
</Page.DataContext>
|
||||
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.Resources>
|
||||
<DataTemplate x:Key="PolylineItemTemplate">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</DataTemplate>
|
||||
|
||||
<map:Map x:Name="map" MinZoomLevel="2" MaxZoomLevel="20" ZoomLevel="11" ManipulationMode="All"
|
||||
Center="{x:Bind ViewModel.MapCenter, Mode=TwoWay}"
|
||||
MapLayer="{x:Bind ViewModel.MapLayers.CurrentMapLayer, Mode=OneWay}"
|
||||
MapProjection="{Binding SelectedValue, ElementName=projectionComboBox,
|
||||
FallbackValue={StaticResource WebMercatorProjection},
|
||||
TargetNullValue={StaticResource WebMercatorProjection}}">
|
||||
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="LocationMemberPath" Value="Location"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<Canvas>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Disabled"/>
|
||||
<VisualState x:Name="PointerOver"/>
|
||||
<VisualState x:Name="Pressed"/>
|
||||
<VisualState x:Name="Selected">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SelectedUnfocused">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SelectedPointerOver">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SelectedPressed">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath" Storyboard.TargetProperty="Opacity" To="0.75" Duration="0"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Path x:Name="selectedPath" Fill="White" Opacity="0">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="12" RadiusY="12"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Fill="Transparent" Stroke="Gray" StrokeThickness="2">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Grid Canvas.Left="15" Canvas.Top="-8">
|
||||
<TextBlock Margin="2,0,2,0" Text="{Binding Name}"/>
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Image x:Name="mapImage" Source="10_535_330.jpg" Opacity="0.5" Stretch="Fill">
|
||||
<map:MapPanel.BoundingBox>
|
||||
<map:BoundingBox South="53.54031" North="53.74871" West="8.08594" East="8.43750"/>
|
||||
</map:MapPanel.BoundingBox>
|
||||
</Image>
|
||||
<Style x:Key="PushpinItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="LocationMemberPath" Value="Location"/>
|
||||
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<map:Pushpin Content="{Binding Name}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
|
||||
<map:MapGraticule x:Name="graticule" Opacity="0.6"
|
||||
Visibility="{Binding IsChecked, ElementName=graticuleCheckBox}"/>
|
||||
<map:Map x:Name="map"
|
||||
MinZoomLevel="2" MaxZoomLevel="21" ZoomLevel="11" ManipulationMode="All"
|
||||
MapLayer="{Binding MapLayers[OpenStreetMap]}"
|
||||
PointerMoved="MapPointerMoved"
|
||||
PointerExited="MapPointerExited">
|
||||
<map:Map.Center>
|
||||
<map:Location Latitude="53.5" Longitude="8.2"/>
|
||||
</map:Map.Center>
|
||||
|
||||
<map:MapScale HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
|
||||
|
||||
<!-- use ItemTemplate or ItemContainerStyle alternatively -->
|
||||
<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
||||
ItemTemplate="{StaticResource PolylineItemTemplate}"/>
|
||||
<!--<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
||||
ItemContainerStyle="{StaticResource PolylineItemStyle}"/>-->
|
||||
|
||||
<map:MapItemsControl ItemsSource="{Binding Points}"
|
||||
ItemContainerStyle="{StaticResource PointItemStyle}"
|
||||
|
|
@ -142,55 +112,29 @@
|
|||
|
||||
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#BFFFFFFF">
|
||||
<TextBlock Margin="2" FontSize="10"
|
||||
local:HyperlinkText.InlinesSource="{Binding MapLayers.CurrentMapLayer.Description}"/>
|
||||
local:HyperlinkText.InlinesSource="{Binding MapLayer.Description, ElementName=map}"/>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<StackPanel Margin="5">
|
||||
<TextBlock Text="Zoom Level" HorizontalAlignment="Center" FontSize="12"/>
|
||||
<Slider Margin="10,-10,10,0" Width="100" SmallChange="0.1"
|
||||
Minimum="{Binding MinZoomLevel, ElementName=map}"
|
||||
Maximum="{Binding MaxZoomLevel, ElementName=map}"
|
||||
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="6" Background="#7FFFFFFF">
|
||||
<local:MapLayersMenuButton
|
||||
Margin="2" Padding="8" ToolTipService.ToolTip="Map Layers"
|
||||
Map="{Binding ElementName=map}"
|
||||
MapLayers="{Binding MapLayers}"
|
||||
MapOverlays="{Binding MapOverlays}"/>
|
||||
|
||||
<StackPanel Margin="5">
|
||||
<TextBlock Text="Heading" HorizontalAlignment="Center" FontSize="12"/>
|
||||
<Slider Margin="10,-10,10,0" Width="100" Minimum="0" Maximum="360" SmallChange="5" LargeChange="45"
|
||||
Value="{Binding Heading, ElementName=map, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
<!--<local:MapProjectionsMenuButton
|
||||
Margin="2" Padding="8" ToolTipService.ToolTip="Map Projections"
|
||||
Map="{Binding ElementName=map}"
|
||||
MapProjections="{Binding MapProjections}"/>-->
|
||||
|
||||
<StackPanel Margin="5,5,25,5">
|
||||
<TextBlock Text="Image Opacity" HorizontalAlignment="Center" FontSize="12"/>
|
||||
<Slider Margin="10,-10,10,0" Width="100" Value="50" ValueChanged="ImageOpacitySliderValueChanged"/>
|
||||
</StackPanel>
|
||||
<Slider Orientation="Vertical" Margin="4,8" Height="100"
|
||||
Minimum="{Binding MinZoomLevel, ElementName=map}"
|
||||
Maximum="{Binding MaxZoomLevel, ElementName=map}"
|
||||
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox x:Name="graticuleCheckBox"
|
||||
VerticalAlignment="Center" Content="Graticule"/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Seamarks"
|
||||
Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
||||
|
||||
<ComboBox Width="250" VerticalAlignment="Center" Margin="0,5"
|
||||
ItemsSource="{Binding MapLayers.MapLayerNames}"
|
||||
SelectedItem="{Binding MapLayers.CurrentMapLayerName, Mode=TwoWay}"/>
|
||||
|
||||
<ComboBox x:Name="projectionComboBox" Width="150" VerticalAlignment="Center" Margin="5"
|
||||
SelectedIndex="0" SelectedValuePath="Tag"
|
||||
SelectedValue="{Binding MapProjection, ElementName=map, Mode=TwoWay}">
|
||||
<ComboBoxItem Content="Web Mercator" Tag="{StaticResource WebMercatorProjection}"/>
|
||||
<ComboBoxItem Content="World Mercator" Tag="{StaticResource WorldMercatorProjection}"/>
|
||||
<ComboBoxItem Content="Equirectangular" Tag="{StaticResource EquirectangularProjection}"/>
|
||||
<ComboBoxItem Content="Orthographic" Tag="{StaticResource OrthographicProjection}"/>
|
||||
<ComboBoxItem Content="Gnomonic" Tag="{StaticResource GnomonicProjection}"/>
|
||||
<ComboBoxItem Content="Stereographic" Tag="{StaticResource StereographicProjection}"/>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Border HorizontalAlignment="Center" VerticalAlignment="Top" Margin="4" Background="#AFFFFFFF">
|
||||
<TextBlock x:Name="mouseLocation" Margin="4,2" Visibility="Collapsed"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
using System;
|
||||
using MapControl;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using MapControl;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Input;
|
||||
|
||||
namespace SampleApplication
|
||||
{
|
||||
|
|
@ -28,30 +29,42 @@ namespace SampleApplication
|
|||
}
|
||||
}
|
||||
|
||||
public MapViewModel ViewModel { get; } = new MapViewModel();
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private void ImageOpacitySliderValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
||||
private void MapPointerMoved(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
if (mapImage != null)
|
||||
var location = map.ViewToLocation(e.GetCurrentPoint(map).Position);
|
||||
var latitude = (int)Math.Round(location.Latitude * 60000d);
|
||||
var longitude = (int)Math.Round(Location.NormalizeLongitude(location.Longitude) * 60000d);
|
||||
var latHemisphere = 'N';
|
||||
var lonHemisphere = 'E';
|
||||
|
||||
if (latitude < 0)
|
||||
{
|
||||
mapImage.Opacity = e.NewValue / 100;
|
||||
latitude = -latitude;
|
||||
latHemisphere = 'S';
|
||||
}
|
||||
|
||||
if (longitude < 0)
|
||||
{
|
||||
longitude = -longitude;
|
||||
lonHemisphere = 'W';
|
||||
}
|
||||
|
||||
mouseLocation.Text = string.Format(CultureInfo.InvariantCulture,
|
||||
"{0} {1:00} {2:00.000}\n{3} {4:000} {5:00.000}",
|
||||
latHemisphere, latitude / 60000, (latitude % 60000) / 1000d,
|
||||
lonHemisphere, longitude / 60000, (longitude % 60000) / 1000d);
|
||||
mouseLocation.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||
private void MapPointerExited(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
map.Children.Insert(map.Children.IndexOf(graticule), ViewModel.MapLayers.SeamarksLayer);
|
||||
}
|
||||
|
||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.Children.Remove(ViewModel.MapLayers.SeamarksLayer);
|
||||
mouseLocation.Visibility = Visibility.Collapsed;
|
||||
mouseLocation.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="UniversalApp.App">
|
||||
<uap:VisualElements DisplayName="XAML Map Control Test Application" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="UniversalApp" BackgroundColor="transparent">
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="SampleApplication.App">
|
||||
<uap:VisualElements DisplayName="XAML Map Control Test Application" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="SampleApplication" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<ProjectGuid>{AA62B4AA-1CA3-4C20-BEB7-B824D0FC4BD1}</ProjectGuid>
|
||||
<OutputType>AppContainerExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>UniversalApp</RootNamespace>
|
||||
<RootNamespace>SampleApplication</RootNamespace>
|
||||
<AssemblyName>UniversalApp</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
|
|
@ -51,12 +51,18 @@
|
|||
<Compile Include="..\Shared\HyperlinkText.cs">
|
||||
<Link>HyperlinkText.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapLayers.cs">
|
||||
<Link>MapLayers.cs</Link>
|
||||
<Compile Include="..\Shared\MapLayersMenuButton.cs">
|
||||
<Link>MapLayersMenuButton.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapProjectionsMenuButton.cs">
|
||||
<Link>MapProjectionsMenuButton.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapViewModel.cs">
|
||||
<Link>MapViewModel.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MenuButton.cs">
|
||||
<Link>MenuButton.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
|
|
|||
|
|
@ -2,24 +2,15 @@
|
|||
x:Class="SampleApplication.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:map="using:MapControl">
|
||||
xmlns:map="using:MapControl"
|
||||
xmlns:local="using:SampleApplication">
|
||||
|
||||
<Grid x:Name="root">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<DataTemplate x:Key="PolylineItemTemplate">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</DataTemplate>
|
||||
|
||||
<Style x:Key="PolylineItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="LocationMemberPath" Value="Location"/>
|
||||
|
|
@ -90,32 +81,22 @@
|
|||
|
||||
</Grid.Resources>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.DataContext>
|
||||
<local:MapViewModel/>
|
||||
</Grid.DataContext>
|
||||
|
||||
<map:Map x:Name="map" ZoomLevel="11" MaxZoomLevel="21" MouseWheelZoomDelta=".5"
|
||||
Center="{Binding MapCenter}"
|
||||
MapLayer="{Binding MapLayers.CurrentMapLayer}"
|
||||
ViewportChanged="MapViewportChanged">
|
||||
<map:Map x:Name="map"
|
||||
MinZoomLevel="2" MaxZoomLevel="21" ZoomLevel="11" MouseWheelZoomDelta="1"
|
||||
MapLayer="{Binding MapLayers[OpenStreetMap]}"
|
||||
ViewportChanged="MapViewportChanged"
|
||||
PointerMoved="MapPointerMoved"
|
||||
PointerExited="MapPointerExited">
|
||||
<map:Map.Center>
|
||||
<map:Location Latitude="53.5" Longitude="8.2"/>
|
||||
</map:Map.Center>
|
||||
|
||||
<Image x:Name="mapImage" Source="10_535_330.jpg" Opacity="0.5" Stretch="Fill">
|
||||
<map:MapPanel.BoundingBox>
|
||||
<map:BoundingBox South="53.54031" North="53.74871" West="8.08594" East="8.43750"/>
|
||||
</map:MapPanel.BoundingBox>
|
||||
</Image>
|
||||
|
||||
<map:MapGraticule x:Name="graticule" Opacity="0.6"
|
||||
Visibility="{Binding IsChecked, ElementName=graticuleCheckBox}"/>
|
||||
|
||||
<map:MapScale HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
|
||||
|
||||
<!-- use ItemTemplate or ItemContainerStyle alternatively -->
|
||||
<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
||||
ItemTemplate="{StaticResource PolylineItemTemplate}"/>
|
||||
<!--<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
||||
ItemContainerStyle="{StaticResource PolylineItemStyle}"/>-->
|
||||
|
||||
<map:MapItemsControl ItemsSource="{Binding Points}"
|
||||
ItemContainerStyle="{StaticResource PointItemStyle}"
|
||||
|
|
@ -131,23 +112,30 @@
|
|||
</map:Pushpin>
|
||||
</map:Map>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#AFFFFFFF">
|
||||
<TextBlock Margin="4,2" FontSize="10" local:HyperlinkText.InlinesSource="{Binding MapLayer.Description, ElementName=map}"/>
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<CheckBox x:Name="graticuleCheckBox"
|
||||
VerticalAlignment="Center" Content="Graticule"/>
|
||||
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="6">
|
||||
<local:MapLayersMenuButton
|
||||
Margin="2" Padding="8" ToolTipService.ToolTip="Map Layers and Overlays"
|
||||
Map="{Binding ElementName=map}"
|
||||
MapLayers="{Binding MapLayers}"
|
||||
MapOverlays="{Binding MapOverlays}"/>
|
||||
|
||||
<CheckBox VerticalAlignment="Center" Content="Seamarks"
|
||||
Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
||||
<!--<local:MapProjectionsMenuButton
|
||||
Margin="2" Padding="8" ToolTipService.ToolTip="Map Projections"
|
||||
Map="{Binding ElementName=map}"
|
||||
MapProjections="{Binding MapProjections}"/>-->
|
||||
|
||||
<ComboBox Width="250" VerticalAlignment="Center" Margin="5"
|
||||
ItemsSource="{Binding MapLayers.MapLayerNames}"
|
||||
SelectedItem="{Binding MapLayers.CurrentMapLayerName, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Slider Orientation="Vertical" Margin="4,8" Height="100"
|
||||
Minimum="{Binding MinZoomLevel, ElementName=map}"
|
||||
Maximum="{Binding MaxZoomLevel, ElementName=map}"
|
||||
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
|
||||
<Border HorizontalAlignment="Center" VerticalAlignment="Top" Margin="4" Background="#AFFFFFFF">
|
||||
<TextBlock x:Name="mouseLocation" Margin="4,2" Visibility="Collapsed"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using MapControl;
|
||||
using MapControl.Caching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -10,8 +12,6 @@ namespace SampleApplication
|
|||
{
|
||||
public sealed partial class MainWindow : Window
|
||||
{
|
||||
private readonly MapViewModel viewModel = new();
|
||||
|
||||
static MainWindow()
|
||||
{
|
||||
try
|
||||
|
|
@ -39,8 +39,6 @@ namespace SampleApplication
|
|||
|
||||
Title = "XAML Map Control - WinUI Sample Application";
|
||||
|
||||
root.DataContext = viewModel;
|
||||
|
||||
if (TileImageLoader.Cache is ImageFileCache)
|
||||
{
|
||||
Activated += WindowActivated;
|
||||
|
|
@ -55,19 +53,42 @@ namespace SampleApplication
|
|||
await ((ImageFileCache)TileImageLoader.Cache).Clean();
|
||||
}
|
||||
|
||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.Children.Insert(map.Children.IndexOf(graticule), viewModel.MapLayers.SeamarksLayer);
|
||||
}
|
||||
|
||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.Children.Remove(viewModel.MapLayers.SeamarksLayer);
|
||||
}
|
||||
|
||||
private void MapViewportChanged(object sender, ViewportChangedEventArgs e)
|
||||
{
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void MapPointerMoved(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
var location = map.ViewToLocation(e.GetCurrentPoint(map).Position);
|
||||
var latitude = (int)Math.Round(location.Latitude * 60000d);
|
||||
var longitude = (int)Math.Round(Location.NormalizeLongitude(location.Longitude) * 60000d);
|
||||
var latHemisphere = 'N';
|
||||
var lonHemisphere = 'E';
|
||||
|
||||
if (latitude < 0)
|
||||
{
|
||||
latitude = -latitude;
|
||||
latHemisphere = 'S';
|
||||
}
|
||||
|
||||
if (longitude < 0)
|
||||
{
|
||||
longitude = -longitude;
|
||||
lonHemisphere = 'W';
|
||||
}
|
||||
|
||||
mouseLocation.Text = string.Format(CultureInfo.InvariantCulture,
|
||||
"{0} {1:00} {2:00.000}\n{3} {4:000} {5:00.000}",
|
||||
latHemisphere, latitude / 60000, (latitude % 60000) / 1000d,
|
||||
lonHemisphere, longitude / 60000, (longitude % 60000) / 1000d);
|
||||
mouseLocation.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void MapPointerExited(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
mouseLocation.Visibility = Visibility.Collapsed;
|
||||
mouseLocation.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@
|
|||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="WinUiApp"
|
||||
Description="WinUiApp"
|
||||
DisplayName="XAML Map Control Test Application"
|
||||
Description="SampleApplication"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||
Square44x44Logo="Assets\Square44x44Logo.png">
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\Shared\10_535_330.jpg" Link="10_535_330.jpg" />
|
||||
<Content Include="..\Shared\10_535_330.jpg" Link="10_535_330.jpg"/>
|
||||
<Content Include="Assets\SplashScreen.scale-200.png" />
|
||||
<Content Include="Assets\LockScreenLogo.scale-200.png" />
|
||||
<Content Include="Assets\Square150x150Logo.scale-200.png" />
|
||||
|
|
|
|||
5
SampleApps/WinUiApp/WinUiApp.csproj.user
Normal file
5
SampleApps/WinUiApp/WinUiApp.csproj.user
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
<ItemGroup />
|
||||
</Project>
|
||||
|
|
@ -5,147 +5,114 @@
|
|||
xmlns:local="clr-namespace:SampleApplication"
|
||||
Title="XAML MapControl - WPF Sample Application" Height="600" Width="900"
|
||||
Stylus.IsPressAndHoldEnabled="False">
|
||||
<Window.Resources>
|
||||
<DataTemplate x:Key="PolylineItemTemplate">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</DataTemplate>
|
||||
|
||||
<Style x:Key="PolylineItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
||||
<EventSetter Event="TouchDown" Handler="MapItemTouchDown"/>
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="Location" Value="{Binding Location}"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<Canvas>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Disabled"/>
|
||||
<VisualState x:Name="MouseOver">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="hoverPath"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.7" Duration="0:0:0.1"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="SelectionStates">
|
||||
<VisualState x:Name="Unselected"/>
|
||||
<VisualState x:Name="Selected">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.7" Duration="0:0:0.1"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Path x:Name="selectedPath" Fill="White" Opacity="0">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="12" RadiusY="12"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path x:Name="hoverPath" StrokeThickness="6" Stroke="White" Opacity="0">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path StrokeThickness="2" Stroke="Gray" Fill="Transparent">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Grid Canvas.Left="15" Canvas.Top="-8">
|
||||
<local:OutlinedText Margin="1" OutlineThickness="1.5" Text="{Binding Name}"
|
||||
Background="{Binding Background, RelativeSource={RelativeSource AncestorType=map:MapBase}}"/>
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Panel.ZIndex" Value="1"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PushpinItemStyle" TargetType="map:MapItem">
|
||||
<EventSetter Event="TouchDown" Handler="MapItemTouchDown"/>
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="Location" Value="{Binding Location}"/>
|
||||
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<map:Pushpin Content="{Binding Name}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Panel.ZIndex" Value="1"/>
|
||||
<Setter Property="Foreground" Value="OrangeRed"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
|
||||
<map:WebMercatorProjection x:Key="WebMercatorProjection"/>
|
||||
<map:WorldMercatorProjection x:Key="WorldMercatorProjection"/>
|
||||
<map:EquirectangularProjection x:Key="EquirectangularProjection"/>
|
||||
<map:OrthographicProjection x:Key="OrthographicProjection"/>
|
||||
<map:GnomonicProjection x:Key="GnomonicProjection"/>
|
||||
<map:StereographicProjection x:Key="StereographicProjection"/>
|
||||
</Window.Resources>
|
||||
|
||||
<Window.DataContext>
|
||||
<local:MapViewModel/>
|
||||
</Window.DataContext>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.Resources>
|
||||
<DataTemplate DataType="{x:Type local:PolylineItem}">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</DataTemplate>
|
||||
|
||||
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
||||
<EventSetter Event="TouchDown" Handler="MapItemTouchDown"/>
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="Location" Value="{Binding Location}"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<Canvas>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Disabled"/>
|
||||
<VisualState x:Name="MouseOver">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="hoverPath"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.7" Duration="0:0:0.1"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="SelectionStates">
|
||||
<VisualState x:Name="Unselected"/>
|
||||
<VisualState x:Name="Selected">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="selectedPath"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.7" Duration="0:0:0.1"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Path x:Name="selectedPath" Fill="White" Opacity="0">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="12" RadiusY="12"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path x:Name="hoverPath" StrokeThickness="6" Stroke="White" Opacity="0">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path StrokeThickness="2" Stroke="Gray" Fill="Transparent">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="8" RadiusY="8"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Grid Canvas.Left="15" Canvas.Top="-8">
|
||||
<local:OutlinedText Margin="1" OutlineThickness="1.5" Text="{Binding Name}"
|
||||
Background="{Binding Background, RelativeSource={RelativeSource AncestorType=map:MapBase}}"/>
|
||||
</Grid>
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Panel.ZIndex" Value="1"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="PushpinItemStyle" TargetType="map:MapItem">
|
||||
<EventSetter Event="TouchDown" Handler="MapItemTouchDown"/>
|
||||
<Setter Property="AutoCollapse" Value="True"/>
|
||||
<Setter Property="Location" Value="{Binding Location}"/>
|
||||
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="map:MapItem">
|
||||
<map:Pushpin Content="{Binding Name}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Panel.ZIndex" Value="1"/>
|
||||
<Setter Property="Foreground" Value="OrangeRed"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<map:WebMercatorProjection x:Key="WebMercatorProjection"/>
|
||||
<map:WorldMercatorProjection x:Key="WorldMercatorProjection"/>
|
||||
<map:EquirectangularProjection x:Key="EquirectangularProjection"/>
|
||||
<map:OrthographicProjection x:Key="OrthographicProjection"/>
|
||||
<map:GnomonicProjection x:Key="GnomonicProjection"/>
|
||||
<map:StereographicProjection x:Key="StereographicProjection"/>
|
||||
</Grid.Resources>
|
||||
|
||||
<Grid.DataContext>
|
||||
<local:MapViewModel/>
|
||||
</Grid.DataContext>
|
||||
|
||||
<map:Map x:Name="map" ZoomLevel="11" MaxZoomLevel="21" MouseWheelZoomDelta="1"
|
||||
Center="{Binding MapCenter}"
|
||||
MapLayer="{Binding MapLayers.CurrentMapLayer}"
|
||||
MapProjection="{Binding SelectedValue, ElementName=projectionComboBox,
|
||||
FallbackValue={StaticResource WebMercatorProjection},
|
||||
TargetNullValue={StaticResource WebMercatorProjection}}"
|
||||
Center="53.5,8.2"
|
||||
MapLayer="{Binding MapLayers[OpenStreetMap]}"
|
||||
MouseLeftButtonDown="MapMouseLeftButtonDown"
|
||||
MouseRightButtonDown="MapMouseRightButtonDown"
|
||||
MouseMove="MapMouseMove" MouseLeave="MapMouseLeave"
|
||||
ManipulationInertiaStarting="MapManipulationInertiaStarting">
|
||||
|
||||
<Image Source="10_535_330.jpg" Stretch="Fill"
|
||||
Opacity="{Binding Value, ElementName=imageOpacitySlider}"
|
||||
map:MapPanel.BoundingBox="53.54031,8.08594,53.74871,8.43750"/>
|
||||
|
||||
<map:MapGraticule x:Name="graticule" Opacity="0.6"
|
||||
Visibility="{Binding IsChecked, ElementName=graticuleCheckBox,
|
||||
Converter={StaticResource BooleanToVisibilityConverter}}"/>
|
||||
|
||||
<map:MapScale HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
|
||||
|
||||
<!-- use ItemTemplate or ItemContainerStyle alternatively -->
|
||||
<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
||||
ItemTemplate="{StaticResource PolylineItemTemplate}"/>
|
||||
<!--<map:MapItemsControl ItemsSource="{Binding Polylines}"
|
||||
ItemContainerStyle="{StaticResource PolylineItemStyle}"/>-->
|
||||
<map:MapItemsControl ItemsSource="{Binding Polylines}"/>
|
||||
|
||||
<map:MapItemsControl ItemsSource="{Binding Points}"
|
||||
ItemContainerStyle="{StaticResource PointItemStyle}"
|
||||
|
|
@ -169,58 +136,34 @@
|
|||
</map:Map>
|
||||
|
||||
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#AFFFFFFF">
|
||||
<TextBlock Margin="4,2" FontSize="10" local:HyperlinkText.InlinesSource="{Binding MapLayer.Description, ElementName=map}"/>
|
||||
<TextBlock Margin="4,2" FontSize="10"
|
||||
local:HyperlinkText.InlinesSource="{Binding MapLayer.Description, ElementName=map}"/>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="mouseLocation" Margin="5" VerticalAlignment="Bottom" FontFamily="Segoe UI Mono"/>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<StackPanel Margin="5">
|
||||
<TextBlock Text="Zoom Level" Margin="0,0,0,2" HorizontalAlignment="Center" FontSize="10"/>
|
||||
<Slider AutoToolTipPlacement="TopLeft" AutoToolTipPrecision="0"
|
||||
Width="75" VerticalAlignment="Center" SmallChange="0.01"
|
||||
Minimum="{Binding MinZoomLevel, ElementName=map}"
|
||||
Maximum="{Binding MaxZoomLevel, ElementName=map}"
|
||||
Value="{Binding TargetZoomLevel, ElementName=map}"/>
|
||||
</StackPanel>
|
||||
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="6">
|
||||
<local:MapLayersMenuButton
|
||||
Margin="2" Padding="6" FontSize="16" ToolTip="Map Layers and Overlays"
|
||||
Map="{Binding ElementName=map}"
|
||||
MapLayers="{Binding MapLayers}"
|
||||
MapOverlays="{Binding MapOverlays}"/>
|
||||
|
||||
<StackPanel Margin="5">
|
||||
<TextBlock Text="Heading" Margin="0,0,0,2" HorizontalAlignment="Center" FontSize="10"/>
|
||||
<Slider AutoToolTipPlacement="TopLeft" AutoToolTipPrecision="0"
|
||||
Width="75" VerticalAlignment="Center" SmallChange="5" LargeChange="45"
|
||||
Minimum="0" Maximum="360" Value="{Binding TargetHeading, ElementName=map}"/>
|
||||
</StackPanel>
|
||||
<!--<local:MapProjectionsMenuButton
|
||||
Margin="2" Padding="6" FontSize="16" ToolTip="Map Projections"
|
||||
Map="{Binding ElementName=map}"
|
||||
MapProjections="{Binding MapProjections}"/>-->
|
||||
|
||||
<StackPanel Margin="5">
|
||||
<TextBlock Text="Image Opacity" Margin="0,0,0,2" HorizontalAlignment="Center" FontSize="10"/>
|
||||
<Slider x:Name="imageOpacitySlider" AutoToolTipPlacement="TopLeft" AutoToolTipPrecision="1"
|
||||
Width="75" VerticalAlignment="Center" Minimum="0" Maximum="1" Value="0.5"/>
|
||||
</StackPanel>
|
||||
<Slider Orientation="Vertical" Margin="8" Height="100"
|
||||
Minimum="{Binding MinZoomLevel, ElementName=map}"
|
||||
Maximum="{Binding MaxZoomLevel, ElementName=map}"
|
||||
Value="{Binding TargetZoomLevel, ElementName=map}"
|
||||
SmallChange="0.1"
|
||||
AutoToolTipPlacement="BottomRight" AutoToolTipPrecision="0"/>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox x:Name="graticuleCheckBox" ToolTip="Graticule Overlay" Margin="8"
|
||||
VerticalAlignment="Bottom" Content="Graticule"/>
|
||||
|
||||
<CheckBox ToolTip="Seamarks Overlay" Margin="8" VerticalAlignment="Bottom" Content="Seamarks"
|
||||
Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
||||
|
||||
<ComboBox ToolTip="Map Layer" Width="200" Margin="5" VerticalAlignment="Bottom"
|
||||
ItemsSource="{Binding MapLayers.MapLayerNames}"
|
||||
SelectedItem="{Binding MapLayers.CurrentMapLayerName}"/>
|
||||
|
||||
<ComboBox x:Name="projectionComboBox" ToolTip="Map Projection" Width="120" Margin="5" VerticalAlignment="Bottom"
|
||||
SelectedValuePath="Tag" SelectedIndex="0">
|
||||
<ComboBoxItem Content="Web Mercator" Tag="{StaticResource WebMercatorProjection}"/>
|
||||
<ComboBoxItem Content="World Mercator" Tag="{StaticResource WorldMercatorProjection}"/>
|
||||
<ComboBoxItem Content="Equirectangular" Tag="{StaticResource EquirectangularProjection}"/>
|
||||
<ComboBoxItem Content="Orthographic" Tag="{StaticResource OrthographicProjection}"/>
|
||||
<ComboBoxItem Content="Gnomonic" Tag="{StaticResource GnomonicProjection}"/>
|
||||
<ComboBoxItem Content="Stereographic" Tag="{StaticResource StereographicProjection}"/>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<local:OutlinedText
|
||||
x:Name="mouseLocation" Margin="4"
|
||||
Background="{Binding Background, ElementName=map}"
|
||||
Foreground="{Binding Foreground, ElementName=map}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Top"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
using System;
|
||||
using MapControl;
|
||||
using MapControl.Caching;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using MapControl;
|
||||
using MapControl.Caching;
|
||||
|
||||
namespace SampleApplication
|
||||
{
|
||||
|
|
@ -108,15 +108,5 @@ namespace SampleApplication
|
|||
mapItem.IsSelected = !mapItem.IsSelected;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.Children.Insert(map.Children.IndexOf(graticule), ((MapViewModel)DataContext).MapLayers.SeamarksLayer);
|
||||
}
|
||||
|
||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.Children.Remove(((MapViewModel)DataContext).MapLayers.SeamarksLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Windows;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
|
|
@ -6,36 +7,49 @@ namespace SampleApplication
|
|||
{
|
||||
public class OutlinedText : FrameworkElement
|
||||
{
|
||||
private GlyphRun glyphRun;
|
||||
private FormattedText text;
|
||||
private Geometry outline;
|
||||
|
||||
public static readonly DependencyProperty TextProperty = TextBlock.TextProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty FontSizeProperty = TextBlock.FontSizeProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty FontFamilyProperty = TextBlock.FontFamilyProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty FontStyleProperty = TextBlock.FontStyleProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty FontWeightProperty = TextBlock.FontWeightProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty FontStretchProperty = TextBlock.FontStretchProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = TextBlock.ForegroundProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty BackgroundProperty = TextBlock.BackgroundProperty.AddOwner(
|
||||
typeof(OutlinedText), new FrameworkPropertyMetadata(Brushes.White, (o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
|
||||
typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata(Brushes.White, (o, e) => ((OutlinedText)o).text = null) { AffectsMeasure = true });
|
||||
|
||||
public static readonly DependencyProperty OutlineThicknessProperty = DependencyProperty.Register(
|
||||
"OutlineThickness", typeof(double), typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => ((OutlinedText)o).glyphRun = null));
|
||||
nameof(OutlineThickness), typeof(double), typeof(OutlinedText),
|
||||
new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => ((OutlinedText)o).text = null));
|
||||
|
||||
public OutlinedText()
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
|
|
@ -93,23 +107,23 @@ namespace SampleApplication
|
|||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
return CheckGlyphRun() ? outline.Bounds.Size : new Size();
|
||||
return ValidateText() ? outline.Bounds.Size : new Size();
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
if (CheckGlyphRun())
|
||||
if (ValidateText())
|
||||
{
|
||||
var location = outline.Bounds.Location;
|
||||
drawingContext.PushTransform(new TranslateTransform(-location.X, -location.Y));
|
||||
drawingContext.DrawGeometry(Background, null, outline);
|
||||
drawingContext.DrawGlyphRun(Foreground, glyphRun);
|
||||
drawingContext.DrawText(text, new Point());
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckGlyphRun()
|
||||
private bool ValidateText()
|
||||
{
|
||||
if (glyphRun == null)
|
||||
if (text == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Text))
|
||||
{
|
||||
|
|
@ -123,19 +137,22 @@ namespace SampleApplication
|
|||
return false;
|
||||
}
|
||||
|
||||
var glyphIndices = new ushort[Text.Length];
|
||||
var advanceWidths = new double[Text.Length];
|
||||
text = new FormattedText(Text,
|
||||
CultureInfo.InvariantCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
FontSize,
|
||||
Foreground,
|
||||
VisualTreeHelper.GetDpi(this).PixelsPerDip);
|
||||
|
||||
for (int i = 0; i < Text.Length; i++)
|
||||
{
|
||||
var glyphIndex = glyphTypeface.CharacterToGlyphMap[Text[i]];
|
||||
glyphIndices[i] = glyphIndex;
|
||||
advanceWidths[i] = glyphTypeface.AdvanceWidths[glyphIndex] * FontSize;
|
||||
}
|
||||
|
||||
glyphRun = new GlyphRun(glyphTypeface, 0, false, FontSize, 1f, glyphIndices, new Point(), advanceWidths, null, null, null, null, null, null);
|
||||
|
||||
outline = glyphRun.BuildGeometry().GetWidenedPathGeometry(new Pen(null, OutlineThickness * 2d));
|
||||
outline = text.BuildGeometry(new Point()).GetWidenedPathGeometry(
|
||||
new Pen
|
||||
{
|
||||
Thickness = OutlineThickness * 2d,
|
||||
LineJoin = PenLineJoin.Round,
|
||||
StartLineCap = PenLineCap.Round,
|
||||
EndLineCap = PenLineCap.Round
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -16,12 +16,18 @@
|
|||
<Compile Include="..\Shared\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="..\Shared\MapLayers.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MapControl\WPF\MapControl.WPF.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Include="..\Shared\10_535_330.jpg" Link="10_535_330.jpg" />
|
||||
<Content Include="..\Shared\10_535_330.jpg" Link="10_535_330.jpg">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net48'">
|
||||
|
|
@ -29,4 +35,9 @@
|
|||
<Reference Include="System.Runtime.Caching" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="App.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
Reference in a new issue