Some cleanup.

This commit is contained in:
ClemensF 2012-08-08 20:42:06 +02:00
parent 65a0d8d51a
commit be3144af07
8 changed files with 217 additions and 236 deletions

View file

@ -3,6 +3,8 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@ -41,7 +43,7 @@ namespace MapControl
public static readonly DependencyProperty TileLayersProperty = DependencyProperty.Register(
"TileLayers", typeof(TileLayerCollection), typeof(Map), new FrameworkPropertyMetadata(
(o, e) => ((Map)o).TileLayersPropertyChanged((TileLayerCollection)e.NewValue),
(o, e) => ((Map)o).TileLayersPropertyChanged((TileLayerCollection)e.OldValue, (TileLayerCollection)e.NewValue),
(o, v) => ((Map)o).CoerceTileLayersProperty((TileLayerCollection)v)));
public static readonly DependencyProperty MainTileLayerProperty = DependencyProperty.Register(
@ -122,14 +124,9 @@ namespace MapControl
}
/// <summary>
/// Raised when the ViewTransform property has changed.
/// Raised when the current viewport has changed.
/// </summary>
public event EventHandler ViewTransformChanged;
/// <summary>
/// Raised when the TileLayers property has changed.
/// </summary>
public event EventHandler TileLayersChanged;
public event Action ViewportChanged;
public double MinZoomLevel { get; set; }
public double MaxZoomLevel { get; set; }
@ -258,7 +255,7 @@ namespace MapControl
}
/// <summary>
/// Gets or sets the map rotation angle in degrees.
/// Gets or sets the map heading, or clockwise rotation angle in degrees.
/// </summary>
public double Heading
{
@ -381,7 +378,7 @@ namespace MapControl
if (transformOrigin != null)
{
viewportOrigin += translation;
UpdateViewTransform();
UpdateTransform();
}
else
{
@ -404,7 +401,7 @@ namespace MapControl
Heading = (((Heading + rotation) % 360d) + 360d) % 360d;
ZoomLevel += Math.Log(scale, 2d);
updateTransform = true;
UpdateViewTransform();
UpdateTransform();
}
TranslateMap(translation);
@ -448,7 +445,7 @@ namespace MapControl
base.OnRenderSizeChanged(sizeInfo);
ResetTransformOrigin();
UpdateViewTransform();
UpdateTransform();
}
protected override void OnRender(DrawingContext drawingContext)
@ -456,21 +453,89 @@ namespace MapControl
drawingContext.DrawRectangle(Background, null, new Rect(RenderSize));
}
protected override void OnViewTransformChanged(Map map)
protected override void OnViewportChanged()
{
base.OnViewTransformChanged(map);
base.OnViewportChanged();
if (ViewTransformChanged != null)
if (ViewportChanged != null)
{
ViewTransformChanged(this, EventArgs.Empty);
ViewportChanged();
}
}
protected internal virtual void OnTileLayersChanged()
private void TileLayerCollectionChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
{
if (tileContainer.TileLayers != null &&
tileContainer.TileLayers.Count > 0 &&
tileContainer.TileLayers[0].HasDarkBackground)
switch (eventArgs.Action)
{
case NotifyCollectionChangedAction.Add:
tileContainer.AddTileLayers(eventArgs.NewStartingIndex, eventArgs.NewItems.Cast<TileLayer>());
break;
case NotifyCollectionChangedAction.Remove:
tileContainer.RemoveTileLayers(eventArgs.OldStartingIndex, eventArgs.OldItems.Cast<TileLayer>());
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
tileContainer.RemoveTileLayers(eventArgs.OldStartingIndex, eventArgs.OldItems.Cast<TileLayer>());
tileContainer.AddTileLayers(eventArgs.NewStartingIndex, eventArgs.NewItems.Cast<TileLayer>());
break;
case NotifyCollectionChangedAction.Reset:
tileContainer.ClearTileLayers();
if (eventArgs.NewItems != null)
{
tileContainer.AddTileLayers(0, eventArgs.NewItems.Cast<TileLayer>());
}
break;
}
UpdateMainTileLayer();
}
private void TileLayersPropertyChanged(TileLayerCollection oldTileLayers, TileLayerCollection newTileLayers)
{
tileContainer.ClearTileLayers();
if (oldTileLayers != null)
{
oldTileLayers.CollectionChanged -= TileLayerCollectionChanged;
}
if (newTileLayers != null)
{
newTileLayers.CollectionChanged += TileLayerCollectionChanged;
tileContainer.AddTileLayers(0, newTileLayers);
}
UpdateMainTileLayer();
}
private TileLayerCollection CoerceTileLayersProperty(TileLayerCollection tileLayers)
{
if (tileLayers == null)
{
tileLayers = new TileLayerCollection();
}
return tileLayers;
}
private void MainTileLayerPropertyChanged(TileLayer mainTileLayer)
{
if (mainTileLayer != null)
{
if (TileLayers.Count == 0)
{
TileLayers.Add(mainTileLayer);
}
else if (TileLayers[0] != mainTileLayer)
{
TileLayers[0] = mainTileLayer;
}
}
if (mainTileLayer != null && mainTileLayer.HasDarkBackground)
{
if (DarkForeground != null)
{
@ -494,63 +559,34 @@ namespace MapControl
Background = LightBackground;
}
}
if (TileLayersChanged != null)
{
TileLayersChanged(this, EventArgs.Empty);
}
}
private void TileLayersPropertyChanged(TileLayerCollection tileLayers)
{
if (tileLayers != null)
{
tileContainer.TileLayers = tileLayers;
MainTileLayer = tileLayers.Count > 0 ? tileLayers[0] : null;
}
}
private TileLayerCollection CoerceTileLayersProperty(TileLayerCollection tileLayers)
{
if (tileLayers == null)
{
tileLayers = new TileLayerCollection();
}
return tileLayers;
}
private void MainTileLayerPropertyChanged(TileLayer mainTileLayer)
{
if (mainTileLayer != null)
{
if (tileContainer.TileLayers.Count == 0)
{
tileContainer.TileLayers.Add(mainTileLayer);
}
else if (tileContainer.TileLayers[0] != mainTileLayer)
{
tileContainer.TileLayers[0] = mainTileLayer;
}
}
}
private TileLayer CoerceMainTileLayerProperty(TileLayer mainTileLayer)
{
if (mainTileLayer == null && tileContainer.TileLayers.Count > 0)
if (mainTileLayer == null && TileLayers.Count > 0)
{
mainTileLayer = tileContainer.TileLayers[0];
mainTileLayer = TileLayers[0];
}
return mainTileLayer;
}
private void UpdateMainTileLayer()
{
TileLayer mainTileLayer = TileLayers.FirstOrDefault();
if (MainTileLayer != mainTileLayer)
{
MainTileLayer = mainTileLayer;
}
}
private void CenterPropertyChanged(Location center)
{
if (updateTransform)
{
ResetTransformOrigin();
UpdateViewTransform();
UpdateTransform();
}
if (centerAnimation == null)
@ -600,7 +636,7 @@ namespace MapControl
{
if (updateTransform)
{
UpdateViewTransform();
UpdateTransform();
}
if (zoomLevelAnimation == null)
@ -649,7 +685,7 @@ namespace MapControl
{
if (updateTransform)
{
UpdateViewTransform();
UpdateTransform();
}
if (headingAnimation == null)
@ -704,20 +740,20 @@ namespace MapControl
return ((heading % 360d) + 360d) % 360d;
}
private void UpdateViewTransform()
private void UpdateTransform()
{
double scale;
if (transformOrigin != null)
{
scale = tileContainer.SetTransform(ZoomLevel, Heading, MapTransform.Transform(transformOrigin), viewportOrigin, RenderSize);
scale = tileContainer.SetViewportTransform(ZoomLevel, Heading, MapTransform.Transform(transformOrigin), viewportOrigin, RenderSize);
updateTransform = false;
Center = ViewportPointToLocation(new Point(RenderSize.Width / 2d, RenderSize.Height / 2d));
updateTransform = true;
}
else
{
scale = tileContainer.SetTransform(ZoomLevel, Heading, MapTransform.Transform(Center), viewportOrigin, RenderSize);
scale = tileContainer.SetViewportTransform(ZoomLevel, Heading, MapTransform.Transform(Center), viewportOrigin, RenderSize);
}
scale *= MapTransform.RelativeScale(Center) / MeterPerDegree; // Pixels per meter at center latitude
@ -728,7 +764,7 @@ namespace MapControl
rotateTransform.Angle = Heading;
scaleRotateTransform.Matrix = scaleTransform.Value * rotateTransform.Value;
OnViewTransformChanged(this);
OnViewportChanged();
}
}
}

View file

@ -7,16 +7,17 @@ using System.Windows;
namespace MapControl
{
internal interface INotifyParentMapChanged
{
void ParentMapChanged(Map oldParentMap, Map newParentMap);
}
/// <summary>
/// Base class for child elements of a MapPanel.
/// </summary>
public abstract class MapElement : FrameworkElement, INotifyParentMapChanged
public abstract class MapElement : FrameworkElement
{
static MapElement()
{
MapPanel.ParentMapProperty.OverrideMetadata(typeof(MapElement),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, ParentMapPropertyChanged));
}
protected MapElement()
{
HorizontalAlignment = HorizontalAlignment.Stretch;
@ -28,23 +29,26 @@ namespace MapControl
get { return MapPanel.GetParentMap(this); }
}
protected abstract void OnViewTransformChanged(Map parentMap);
protected abstract void OnViewportChanged();
private void OnViewTransformChanged(object sender, EventArgs eventArgs)
private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
{
OnViewTransformChanged((Map)sender);
}
MapElement mapElement = obj as MapElement;
void INotifyParentMapChanged.ParentMapChanged(Map oldParentMap, Map newParentMap)
{
if (oldParentMap != null)
if (mapElement != null)
{
oldParentMap.ViewTransformChanged -= OnViewTransformChanged;
}
Map oldParentMap = eventArgs.OldValue as Map;
Map newParentMap = eventArgs.NewValue as Map;
if (newParentMap != null)
{
newParentMap.ViewTransformChanged += OnViewTransformChanged;
if (oldParentMap != null)
{
oldParentMap.ViewportChanged -= mapElement.OnViewportChanged;
}
if (newParentMap != null)
{
newParentMap.ViewportChanged += mapElement.OnViewportChanged;
}
}
}
}

View file

@ -125,8 +125,9 @@ namespace MapControl
return visual;
}
protected override void OnViewTransformChanged(Map parentMap)
protected override void OnViewportChanged()
{
Map parentMap = ParentMap;
Rect bounds = parentMap.ViewportTransform.Inverse.TransformBounds(new Rect(parentMap.RenderSize));
Location loc1 = parentMap.MapTransform.TransformBack(bounds.TopLeft);
Location loc2 = parentMap.MapTransform.TransformBack(bounds.BottomRight);
@ -195,7 +196,7 @@ namespace MapControl
private void UpdateBrush()
{
pen.Brush = null;
OnViewTransformChanged(ParentMap);
OnViewportChanged();
}
private static string CoordinateString(double value, string format, string hemispheres)

View file

@ -15,7 +15,7 @@ namespace MapControl
/// coordinates. IsInsideMapBounds indicates if the viewport coordinates are located
/// inside the visible part of the map.
/// </summary>
public class MapPanel : Panel, INotifyParentMapChanged
public class MapPanel : Panel
{
public static readonly DependencyProperty ParentMapProperty = DependencyProperty.RegisterAttached(
"ParentMap", typeof(Map), typeof(MapPanel),
@ -102,8 +102,10 @@ namespace MapControl
return finalSize;
}
protected virtual void OnViewTransformChanged(Map parentMap)
protected virtual void OnViewportChanged()
{
Map parentMap = ParentMap;
foreach (UIElement element in InternalChildren)
{
Location location = GetLocation(element);
@ -115,31 +117,24 @@ namespace MapControl
}
}
private void OnViewTransformChanged(object sender, EventArgs eventArgs)
{
OnViewTransformChanged((Map)sender);
}
void INotifyParentMapChanged.ParentMapChanged(Map oldParentMap, Map newParentMap)
{
if (oldParentMap != null && oldParentMap != this)
{
oldParentMap.ViewTransformChanged -= OnViewTransformChanged;
}
if (newParentMap != null && newParentMap != this)
{
newParentMap.ViewTransformChanged += OnViewTransformChanged;
}
}
private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
{
INotifyParentMapChanged notifyChanged = obj as INotifyParentMapChanged;
MapPanel mapPanel = obj as MapPanel;
if (notifyChanged != null)
if (mapPanel != null)
{
notifyChanged.ParentMapChanged(eventArgs.OldValue as Map, eventArgs.NewValue as Map);
Map oldParentMap = eventArgs.OldValue as Map;
Map newParentMap = eventArgs.NewValue as Map;
if (oldParentMap != null && oldParentMap != mapPanel)
{
oldParentMap.ViewportChanged -= mapPanel.OnViewportChanged;
}
if (newParentMap != null && newParentMap != mapPanel)
{
newParentMap.ViewportChanged += mapPanel.OnViewportChanged;
}
}
}

View file

@ -156,13 +156,13 @@ namespace MapControl
AddVisualChild(visual);
}
protected override void OnViewTransformChanged(Map parentMap)
protected override void OnViewportChanged()
{
double scale = 1d;
if (TransformStroke)
{
scale = parentMap.CenterScale * Map.MeterPerDegree;
scale = ParentMap.CenterScale * Map.MeterPerDegree;
}
drawing.Pen.Thickness = scale * StrokeThickness;
@ -175,12 +175,10 @@ namespace MapControl
protected void UpdateGeometry(bool closed)
{
Map parentMap = MapPanel.GetParentMap(this);
if (parentMap != null && Locations != null && Locations.Count > 0)
if (ParentMap != null && Locations != null && Locations.Count > 0)
{
drawing.Geometry = CreateGeometry(parentMap, Locations, closed);
OnViewTransformChanged(parentMap);
drawing.Geometry = CreateGeometry(Locations, closed);
OnViewportChanged();
}
else
{
@ -190,28 +188,26 @@ namespace MapControl
private void UpdatePenThickness()
{
Map parentMap = MapPanel.GetParentMap(this);
if (parentMap != null)
if (ParentMap != null)
{
OnViewTransformChanged(parentMap);
OnViewportChanged();
}
}
private Geometry CreateGeometry(Map parentMap, LocationCollection locations, bool closed)
private Geometry CreateGeometry(LocationCollection locations, bool closed)
{
StreamGeometry geometry = new StreamGeometry
{
Transform = parentMap.ViewportTransform
Transform = ParentMap.ViewportTransform
};
using (StreamGeometryContext sgc = geometry.Open())
{
sgc.BeginFigure(parentMap.MapTransform.Transform(locations.First()), closed, closed);
sgc.BeginFigure(ParentMap.MapTransform.Transform(locations.First()), closed, closed);
if (Locations.Count > 1)
{
sgc.PolyLineTo(parentMap.MapTransform.Transform(locations.Skip(1)), true, true);
sgc.PolyLineTo(ParentMap.MapTransform.Transform(locations.Skip(1)), true, true);
}
}

View file

@ -3,8 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
@ -23,44 +22,56 @@ namespace MapControl
private double zoomLevel;
private int tileZoomLevel;
private Int32Rect tileGrid;
private TileLayerCollection tileLayers;
private readonly DispatcherTimer updateTimer;
private readonly MatrixTransform viewportTransform = new MatrixTransform();
public readonly MatrixTransform ViewportTransform = new MatrixTransform();
public TileContainer()
{
updateTimer = new DispatcherTimer(TimeSpan.FromSeconds(0.5), DispatcherPriority.Background, UpdateTiles, Dispatcher);
}
public TileLayerCollection TileLayers
public void AddTileLayers(int index, IEnumerable<TileLayer> tileLayers)
{
get { return tileLayers; }
set
Matrix transform = GetVisualTransform();
foreach (TileLayer tileLayer in tileLayers)
{
if (tileLayers != null)
if (string.IsNullOrEmpty(tileLayer.Name))
{
tileLayers.CollectionChanged -= TileLayersChanged;
throw new ArgumentException("TileLayer.Name property must not be null or empty.");
}
tileLayers = value;
ClearChildren();
if (tileLayers != null)
{
tileLayers.CollectionChanged += TileLayersChanged;
AddChildren(0, tileLayers);
}
((Map)VisualParent).OnTileLayersChanged();
Children.Insert(index++, tileLayer);
tileLayer.TransformMatrix = transform;
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
}
}
public Transform ViewportTransform
public void RemoveTileLayers(int index, IEnumerable<TileLayer> tileLayers)
{
get { return viewportTransform; }
int count = 0;
foreach (TileLayer tileLayer in tileLayers)
{
tileLayer.ClearTiles();
count++;
}
Children.RemoveRange(index, count);
}
public double SetTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point viewportOrigin, Size viewportSize)
public void ClearTileLayers()
{
foreach (TileLayer tileLayer in Children)
{
tileLayer.ClearTiles();
}
Children.Clear();
}
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point viewportOrigin, Size viewportSize)
{
zoomLevel = mapZoomLevel;
rotation = mapRotation;
@ -75,16 +86,13 @@ namespace MapControl
transform.Scale(scale, scale);
transform.Translate(offset.X, offset.Y);
transform.RotateAt(rotation, origin.X, origin.Y);
viewportTransform.Matrix = transform;
ViewportTransform.Matrix = transform;
transform = GetVisualTransform();
if (tileLayers != null)
foreach (TileLayer tileLayer in Children)
{
foreach (TileLayer tileLayer in tileLayers)
{
tileLayer.TransformMatrix = transform;
}
tileLayer.TransformMatrix = transform;
}
updateTimer.IsEnabled = true;
@ -113,7 +121,7 @@ namespace MapControl
int zoom = (int)Math.Floor(zoomLevel + 1d - zoomLevelSwitchOffset);
int numTiles = 1 << zoom;
double mapToTileScale = (double)numTiles / 360d;
Matrix transform = viewportTransform.Matrix;
Matrix transform = ViewportTransform.Matrix;
transform.Invert(); // view to map coordinates
transform.Translate(180d, -180d);
transform.Scale(mapToTileScale, -mapToTileScale); // map coordinates to tile indices
@ -142,77 +150,12 @@ namespace MapControl
tileGrid = grid;
transform = GetVisualTransform();
if (tileLayers != null)
foreach (TileLayer tileLayer in Children)
{
foreach (TileLayer tileLayer in tileLayers)
{
tileLayer.TransformMatrix = transform;
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
}
tileLayer.TransformMatrix = transform;
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
}
}
}
private void TileLayersChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
{
switch (eventArgs.Action)
{
case NotifyCollectionChangedAction.Add:
AddChildren(eventArgs.NewStartingIndex, eventArgs.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
RemoveChildren(eventArgs.OldStartingIndex, eventArgs.OldItems);
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
RemoveChildren(eventArgs.OldStartingIndex, eventArgs.OldItems);
AddChildren(eventArgs.NewStartingIndex, eventArgs.NewItems);
break;
case NotifyCollectionChangedAction.Reset:
ClearChildren();
if (eventArgs.NewItems != null)
{
AddChildren(0, eventArgs.NewItems);
}
break;
}
((Map)VisualParent).OnTileLayersChanged();
}
private void AddChildren(int index, IList layers)
{
Matrix transform = GetVisualTransform();
foreach (TileLayer tileLayer in layers)
{
Children.Insert(index++, tileLayer);
tileLayer.TransformMatrix = transform;
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
}
}
private void RemoveChildren(int index, IList layers)
{
foreach (TileLayer tileLayer in layers)
{
tileLayer.ClearTiles();
}
Children.RemoveRange(index, layers.Count);
}
private void ClearChildren()
{
foreach (TileLayer tileLayer in Children)
{
tileLayer.ClearTiles();
}
Children.Clear();
}
}
}

View file

@ -27,7 +27,6 @@ namespace MapControl
tileImageLoader = new TileImageLoader(this);
VisualEdgeMode = EdgeMode.Aliased;
VisualTransform = new MatrixTransform();
Name = string.Empty;
MinZoomLevel = 1;
MaxZoomLevel = 18;
MaxParallelDownloads = 8;
@ -59,7 +58,7 @@ namespace MapControl
tileImageLoader.CancelGetTiles();
if (VisualParent != null && TileSource != null)
if (TileSource != null)
{
SelectTiles();
RenderTiles();
@ -76,11 +75,11 @@ namespace MapControl
private void SelectTiles()
{
TileContainer tileContainer = VisualParent as TileContainer;
int maxZoomLevel = Math.Min(zoomLevel, MaxZoomLevel);
int minZoomLevel = maxZoomLevel;
ContainerVisual parent = Parent as ContainerVisual;
if (tileContainer != null && tileContainer.TileLayers.IndexOf(this) == 0)
if (parent != null && parent.Children.IndexOf(this) == 0)
{
minZoomLevel = MinZoomLevel;
}

View file

@ -11,6 +11,7 @@
<local:SampleItemCollection x:Key="Polylines"/>
<local:SampleItemCollection x:Key="Points"/>
<local:SampleItemCollection x:Key="Pushpins"/>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<DataTemplate x:Key="PolylineItemTemplate">
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
</DataTemplate>
@ -64,6 +65,7 @@
</Style>
<Style x:Key="PushpinItemStyle" TargetType="map:MapItem">
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
<Setter Property="Visibility" Value="{Binding (map:MapPanel.IsInsideMapBounds), Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource Self}}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Template">
@ -85,10 +87,10 @@
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<map:Map Name="map" IsManipulationEnabled="True" Margin="2" FontSize="10"
<map:Map Name="map" IsManipulationEnabled="True" Margin="2" FontSize="10"
LightForeground="Black" LightBackground="White" DarkForeground="White" DarkBackground="#FF3F3F3F"
Center="53.5,8.2" ZoomLevel="11"
MainTileLayer="{Binding ElementName=tileLayerComboBox, Path=SelectedItem}"
MainTileLayer="{Binding SelectedItem, ElementName=tileLayerComboBox}"
ManipulationInertiaStarting="MapManipulationInertiaStarting"
MouseMove="MapMouseMove" MouseLeave="MapMouseLeave">
<map:MapGraticule Opacity="0.6"/>
@ -100,9 +102,10 @@
<map:MapItemsControl ItemsSource="{StaticResource Pushpins}"
ItemContainerStyle="{StaticResource PushpinItemStyle}"
IsSynchronizedWithCurrentItem="True"/>
<map:Pushpin Location="53.5,8.2" Background="Yellow" Foreground="Blue">N 53° 30' E 8° 12'</map:Pushpin>
<map:Pushpin Location="53.5,8.2" Background="Yellow" Foreground="Blue" Content="N 53° 30' E 8° 12'"
Visibility="{Binding (map:MapPanel.IsInsideMapBounds), Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource Self}}"/>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="2,0,0,0" FontSize="10"
Text="{Binding ElementName=map, Path=MainTileLayer.Description}"/>
Text="{Binding MainTileLayer.Description, ElementName=map}"/>
</map:Map>
<Grid Grid.Row="1" Margin="2">
<Grid.ColumnDefinitions>
@ -112,9 +115,9 @@
<TextBlock Name="mouseLocation" Margin="4" VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Slider Name="zoomSlider" ToolTip="Zoom Level" Margin="4,0,4,0" Width="100" Minimum="1" Maximum="20" SmallChange="0.01"
Value="{Binding ElementName=map, Path=TargetZoomLevel}" />
Value="{Binding TargetZoomLevel, ElementName=map}" />
<Slider Name="headingSlider" ToolTip="Heading" Margin="4,0,4,0" Width="100" Minimum="0" Maximum="360" SmallChange="10" LargeChange="45"
Value="{Binding ElementName=map, Path=TargetHeading}"/>
Value="{Binding TargetHeading, ElementName=map}"/>
<CheckBox ToolTip="Map Overlay" Margin="4,0,4,0" VerticalAlignment="Center" Content="Seamarks" Click="SeamarksClick"/>
<ComboBox Name="tileLayerComboBox" ToolTip="Main Tile Layer" Margin="4,0,4,0" DisplayMemberPath="Name" SelectedIndex="0">
<ComboBox.Items>
@ -129,7 +132,11 @@
<map:TileLayer Name="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest &amp; OpenStreetMap Contributors"
TileSource="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
<!--<map:TileLayer Name="Google Maps" Description="Google Maps - © {y} Google"
<!-- Note: The providers of the below TileLayers do not allow access to their
map content without using their APIs (i.e. Google Maps API or Bing Maps API).
Hence the declarations below are for demonstration purpose only. -->
<map:TileLayer Name="Google Maps" Description="Google Maps - © {y} Google"
TileSource="http://mt{i}.google.com/vt/x={x}&amp;y={y}&amp;z={z}" MaxZoomLevel="20"/>
<map:TileLayer Name="Google Images" Description="Google Maps - © {y} Google"
TileSource="http://khm{i}.google.com/kh/v=113&amp;x={x}&amp;y={y}&amp;z={z}" MaxZoomLevel="20" HasDarkBackground="True"/>
@ -138,9 +145,9 @@
<map:TileLayer Name="Bing Images" Description="Bing Maps - © {y} Microsoft Corporation"
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/a{q}.jpeg?g=0" MaxZoomLevel="20" HasDarkBackground="True"/>
<map:TileLayer Name="Bing Hybrid" Description="Bing Maps - © {y} Microsoft Corporation"
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/h{q}.jpeg?g=0&amp;stl=h" MaxZoomLevel="20" HasDarkBackground="True"/>-->
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/h{q}.jpeg?g=0&amp;stl=h" MaxZoomLevel="20" HasDarkBackground="True"/>
<!-- The TileLayer below uses an ImageTileSource that bypasses caching of map tile images -->
<!-- The TileLayer below uses an ImageTileSource, which bypasses caching of map tile images -->
<map:TileLayer Name="OSM Uncached" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
<map:TileLayer.TileSource>