Version 1.2.0: Added classes MapShape, MapRectangle and MapImage.

This commit is contained in:
ClemensF 2013-04-12 19:59:16 +02:00
parent ec27d16119
commit 9b218ef376
45 changed files with 846 additions and 565 deletions

View file

@ -9,6 +9,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]

View file

@ -9,6 +9,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]

View file

@ -22,7 +22,7 @@ namespace MapControl
private const FillBehavior AnimationFillBehavior = FillBehavior.HoldEnd;
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
"Foreground", typeof(Brush), typeof(MapBase), null);
"Foreground", typeof(Brush), typeof(MapBase), new PropertyMetadata(new SolidColorBrush(Colors.Black)));
partial void Initialize()
{

View file

@ -108,7 +108,7 @@ namespace MapControl
public MapBase()
{
SetValue(MapPanel.ParentMapProperty, this);
SetParentMap();
Background = LightBackground;
TileLayers = new TileLayerCollection();

View file

@ -75,15 +75,17 @@
<Compile Include="MapBase.Silverlight.WinRT.cs" />
<Compile Include="MapGraticule.cs" />
<Compile Include="MapGraticule.Silverlight.WinRT.cs" />
<Compile Include="MapImage.cs" />
<Compile Include="MapItem.Silverlight.WinRT.cs" />
<Compile Include="MapItemsControl.cs" />
<Compile Include="MapItemsControl.Silverlight.WinRT.cs" />
<Compile Include="MapOverlay.cs" />
<Compile Include="MapOverlay.Silverlight.WinRT.cs" />
<Compile Include="MapPanel.cs" />
<Compile Include="MapPanel.Silverlight.WinRT.cs" />
<Compile Include="MapRectangle.cs" />
<Compile Include="MapShape.cs" />
<Compile Include="MapPolyline.cs" />
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
<Compile Include="MapShape.Silverlight.WinRT.cs" />
<Compile Include="MapTransform.cs" />
<Compile Include="MatrixEx.cs" />
<Compile Include="MercatorTransform.cs" />

View file

@ -46,7 +46,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="MapGraticule.WPF.cs" />
<Compile Include="MapOverlay.WPF.cs" />
<Compile Include="Location.cs" />
<Compile Include="LocationCollection.cs" />
<Compile Include="LocationCollectionConverter.cs" />
@ -60,10 +59,14 @@
<Compile Include="MapItem.WPF.cs" />
<Compile Include="MapItemsControl.cs" />
<Compile Include="MapItemsControl.WPF.cs" />
<Compile Include="MapImage.cs" />
<Compile Include="MapPanel.cs" />
<Compile Include="MapPanel.WPF.cs" />
<Compile Include="MapPolyline.cs" />
<Compile Include="MapPolyline.WPF.cs" />
<Compile Include="MapRectangle.cs" />
<Compile Include="MapShape.cs" />
<Compile Include="MapShape.WPF.cs" />
<Compile Include="MapTransform.cs" />
<Compile Include="MercatorTransform.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View file

@ -6,97 +6,219 @@ using System;
using System.Linq;
#if NETFX_CORE
using Windows.Foundation;
using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Data;
#else
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Data;
#endif
namespace MapControl
{
public partial class MapGraticule
public partial class MapGraticule : MapPanel
{
public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register(
"FontFamily", typeof(FontFamily), typeof(MapGraticule),
new PropertyMetadata(default(FontFamily), (o, e) => ((MapGraticule)o).OnViewportChanged()));
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
"FontSize", typeof(double), typeof(MapGraticule),
new PropertyMetadata(10d, (o, e) => ((MapGraticule)o).OnViewportChanged()));
public static readonly DependencyProperty FontStyleProperty = DependencyProperty.Register(
"FontStyle", typeof(FontStyle), typeof(MapGraticule),
new PropertyMetadata(default(FontStyle), (o, e) => ((MapGraticule)o).OnViewportChanged()));
public static readonly DependencyProperty FontStretchProperty = DependencyProperty.Register(
"FontStretch", typeof(FontStretch), typeof(MapGraticule),
new PropertyMetadata(default(FontStretch), (o, e) => ((MapGraticule)o).OnViewportChanged()));
public static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register(
"FontWeight", typeof(FontWeight), typeof(MapGraticule),
new PropertyMetadata(FontWeights.Normal, (o, e) => ((MapGraticule)o).OnViewportChanged()));
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
"Foreground", typeof(Brush), typeof(MapGraticule),
new PropertyMetadata(null, (o, e) => ((MapGraticule)o).OnViewportChanged()));
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
"Stroke", typeof(Brush), typeof(MapGraticule),
new PropertyMetadata(null, (o, e) => ((MapGraticule)o).path.Stroke = (Brush)e.NewValue));
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
"StrokeThickness", typeof(double), typeof(MapGraticule),
new PropertyMetadata(0.5, (o, e) => ((MapGraticule)o).path.StrokeThickness = (double)e.NewValue));
private readonly Path path;
private Location graticuleStart;
private Location graticuleEnd;
public MapGraticule()
{
IsHitTestVisible = false;
path = new Path
{
Stroke = Stroke,
StrokeThickness = StrokeThickness
};
Children.Add(path);
}
public FontFamily FontFamily
{
get { return (FontFamily)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
public double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
public FontStyle FontStyle
{
get { return (FontStyle)GetValue(FontStyleProperty); }
set { SetValue(FontStyleProperty, value); }
}
public FontStretch FontStretch
{
get { return (FontStretch)GetValue(FontStretchProperty); }
set { SetValue(FontStretchProperty, value); }
}
public FontWeight FontWeight
{
get { return (FontWeight)GetValue(FontWeightProperty); }
set { SetValue(FontWeightProperty, value); }
}
public Brush Foreground
{
get { return (Brush)GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
public Brush Stroke
{
get { return (Brush)GetValue(StrokeProperty); }
set { SetValue(StrokeProperty, value); }
}
public double StrokeThickness
{
get { return (double)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
protected override void OnViewportChanged()
{
var parentMap = MapPanel.GetParentMap(this);
var bounds = parentMap.ViewportTransform.Inverse.TransformBounds(new Rect(0d, 0d, parentMap.RenderSize.Width, parentMap.RenderSize.Height));
var start = parentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y));
var end = parentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height));
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, parentMap.ZoomLevel) * 256d);
var spacing = LineSpacings[LineSpacings.Length - 1];
if (spacing >= minSpacing)
if (ParentMap != null)
{
spacing = LineSpacings.FirstOrDefault(s => s >= minSpacing);
}
var labelsStart = new Location(
Math.Ceiling(start.Latitude / spacing) * spacing,
Math.Ceiling(start.Longitude / spacing) * spacing);
var labelsEnd = new Location(
Math.Floor(end.Latitude / spacing) * spacing,
Math.Floor(end.Longitude / spacing) * spacing);
var linesStart = new Location(
Math.Min(Math.Max(labelsStart.Latitude - spacing, -parentMap.MapTransform.MaxLatitude), parentMap.MapTransform.MaxLatitude),
labelsStart.Longitude - spacing);
var linesEnd = new Location(
Math.Min(Math.Max(labelsEnd.Latitude + spacing, -parentMap.MapTransform.MaxLatitude), parentMap.MapTransform.MaxLatitude),
labelsEnd.Longitude + spacing);
if (!linesStart.Equals(graticuleStart) || !linesEnd.Equals(graticuleEnd))
{
graticuleStart = linesStart;
graticuleEnd = linesEnd;
Geometry.Figures.Clear();
Geometry.Transform = parentMap.ViewportTransform;
for (var lat = labelsStart.Latitude; lat <= end.Latitude; lat += spacing)
if (path.Data == null)
{
var figure = new PathFigure
{
StartPoint = parentMap.MapTransform.Transform(new Location(lat, linesStart.Longitude)),
IsClosed = false,
IsFilled = false
};
path.Data = new PathGeometry();
figure.Segments.Add(new LineSegment
if (Foreground == null)
{
Point = parentMap.MapTransform.Transform(new Location(lat, linesEnd.Longitude)),
});
SetBinding(ForegroundProperty, new Binding()
{
Source = ParentMap,
Path = new PropertyPath("Foreground")
});
}
Geometry.Figures.Add(figure);
if (Stroke == null)
{
SetBinding(StrokeProperty, new Binding()
{
Source = ParentMap,
Path = new PropertyPath("Foreground")
});
}
}
for (var lon = labelsStart.Longitude; lon <= end.Longitude; lon += spacing)
var geometry = (PathGeometry)path.Data;
var bounds = ParentMap.ViewportTransform.Inverse.TransformBounds(new Rect(0d, 0d, ParentMap.RenderSize.Width, ParentMap.RenderSize.Height));
var start = ParentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y));
var end = ParentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height));
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * 256d);
var spacing = LineSpacings[LineSpacings.Length - 1];
if (spacing >= minSpacing)
{
var figure = new PathFigure
{
StartPoint = parentMap.MapTransform.Transform(new Location(linesStart.Latitude, lon)),
IsClosed = false,
IsFilled = false
};
figure.Segments.Add(new LineSegment
{
Point = parentMap.MapTransform.Transform(new Location(linesEnd.Latitude, lon)),
});
Geometry.Figures.Add(figure);
spacing = LineSpacings.FirstOrDefault(s => s >= minSpacing);
}
var childIndex = 1; // 0 for Path
var labelsStart = new Location(
Math.Ceiling(start.Latitude / spacing) * spacing,
Math.Ceiling(start.Longitude / spacing) * spacing);
if (Foreground != null)
var labelsEnd = new Location(
Math.Floor(end.Latitude / spacing) * spacing,
Math.Floor(end.Longitude / spacing) * spacing);
var linesStart = new Location(
Math.Min(Math.Max(labelsStart.Latitude - spacing, -ParentMap.MapTransform.MaxLatitude), ParentMap.MapTransform.MaxLatitude),
labelsStart.Longitude - spacing);
var linesEnd = new Location(
Math.Min(Math.Max(labelsEnd.Latitude + spacing, -ParentMap.MapTransform.MaxLatitude), ParentMap.MapTransform.MaxLatitude),
labelsEnd.Longitude + spacing);
if (!linesStart.Equals(graticuleStart) || !linesEnd.Equals(graticuleEnd))
{
graticuleStart = linesStart;
graticuleEnd = linesEnd;
geometry.Figures.Clear();
geometry.Transform = ParentMap.ViewportTransform;
for (var lat = labelsStart.Latitude; lat <= end.Latitude; lat += spacing)
{
var figure = new PathFigure
{
StartPoint = ParentMap.MapTransform.Transform(new Location(lat, linesStart.Longitude)),
IsClosed = false,
IsFilled = false
};
figure.Segments.Add(new LineSegment
{
Point = ParentMap.MapTransform.Transform(new Location(lat, linesEnd.Longitude)),
});
geometry.Figures.Add(figure);
}
for (var lon = labelsStart.Longitude; lon <= end.Longitude; lon += spacing)
{
var figure = new PathFigure
{
StartPoint = ParentMap.MapTransform.Transform(new Location(linesStart.Latitude, lon)),
IsClosed = false,
IsFilled = false
};
figure.Segments.Add(new LineSegment
{
Point = ParentMap.MapTransform.Transform(new Location(linesEnd.Latitude, lon)),
});
geometry.Figures.Add(figure);
}
var childIndex = 1; // 0 for Path
var format = spacing < 1d ? "{0} {1}°{2:00}'" : "{0} {1}°";
var measureSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
@ -113,7 +235,17 @@ namespace MapControl
}
else
{
label = new TextBlock { RenderTransform = new TransformGroup() };
label = new TextBlock
{
RenderTransform = new TransformGroup()
};
label.SetBinding(TextBlock.ForegroundProperty, new Binding
{
Source = this,
Path = new PropertyPath("Foreground")
});
Children.Add(label);
}
@ -126,9 +258,8 @@ namespace MapControl
label.FontSize = FontSize;
label.FontStyle = FontStyle;
label.FontWeight = FontWeight;
label.FontStretch = FontStretch;
label.Foreground = Foreground;
label.FontWeight = FontWeight;
label.Text = string.Format("{0}\n{1}",
CoordinateString(lat, format, "NS"),
@ -141,7 +272,7 @@ namespace MapControl
if (transformGroup.Children.Count == 0)
{
transformGroup.Children.Add(new TranslateTransform());
transformGroup.Children.Add(parentMap.RotateTransform);
transformGroup.Children.Add(ParentMap.RotateTransform);
}
var translateTransform = (TranslateTransform)transformGroup.Children[0];
@ -151,13 +282,17 @@ namespace MapControl
MapPanel.SetLocation(label, location);
}
}
}
while (Children.Count > childIndex)
{
Children.RemoveAt(Children.Count - 1);
while (Children.Count > childIndex)
{
Children.RemoveAt(Children.Count - 1);
}
}
}
else
{
path.Data = null;
}
base.OnViewportChanged();
}

View file

@ -9,18 +9,30 @@ using System.Windows.Media;
namespace MapControl
{
public partial class MapGraticule
public partial class MapGraticule : MapOverlay
{
static MapGraticule()
{
UIElement.IsHitTestVisibleProperty.OverrideMetadata(
typeof(MapGraticule), new FrameworkPropertyMetadata(false));
MapOverlay.StrokeThicknessProperty.OverrideMetadata(
typeof(MapGraticule), new FrameworkPropertyMetadata(0.5));
}
protected override void OnViewportChanged()
{
InvalidateVisual();
}
protected override void OnRender(DrawingContext drawingContext)
{
var parentMap = MapPanel.GetParentMap(this);
if (parentMap != null)
if (ParentMap != null)
{
var bounds = parentMap.ViewportTransform.Inverse.TransformBounds(new Rect(parentMap.RenderSize));
var start = parentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y));
var end = parentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height));
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, parentMap.ZoomLevel) * 256d);
var bounds = ParentMap.ViewportTransform.Inverse.TransformBounds(new Rect(ParentMap.RenderSize));
var start = ParentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y));
var end = ParentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height));
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * 256d);
var spacing = LineSpacings[LineSpacings.Length - 1];
if (spacing >= minSpacing)
@ -35,15 +47,15 @@ namespace MapControl
for (var lat = labelsStart.Latitude; lat <= end.Latitude; lat += spacing)
{
drawingContext.DrawLine(Pen,
parentMap.LocationToViewportPoint(new Location(lat, start.Longitude)),
parentMap.LocationToViewportPoint(new Location(lat, end.Longitude)));
ParentMap.LocationToViewportPoint(new Location(lat, start.Longitude)),
ParentMap.LocationToViewportPoint(new Location(lat, end.Longitude)));
}
for (var lon = labelsStart.Longitude; lon <= end.Longitude; lon += spacing)
{
drawingContext.DrawLine(Pen,
parentMap.LocationToViewportPoint(new Location(start.Latitude, lon)),
parentMap.LocationToViewportPoint(new Location(end.Latitude, lon)));
ParentMap.LocationToViewportPoint(new Location(start.Latitude, lon)),
ParentMap.LocationToViewportPoint(new Location(end.Latitude, lon)));
}
if (Foreground != null && Foreground != Brushes.Transparent)
@ -55,13 +67,13 @@ namespace MapControl
for (var lon = labelsStart.Longitude; lon <= end.Longitude; lon += spacing)
{
var t = StrokeThickness / 2d;
var p = parentMap.LocationToViewportPoint(new Location(lat, lon));
var p = ParentMap.LocationToViewportPoint(new Location(lat, lon));
var latPos = new Point(p.X + t + 2d, p.Y - t - FontSize / 4d);
var lonPos = new Point(p.X + t + 2d, p.Y + t + FontSize);
var latLabel = CoordinateString(lat, format, "NS");
var lonLabel = CoordinateString(Location.NormalizeLongitude(lon), format, "EW");
drawingContext.PushTransform(new RotateTransform(parentMap.Heading, p.X, p.Y));
drawingContext.PushTransform(new RotateTransform(ParentMap.Heading, p.X, p.Y));
drawingContext.DrawGlyphRun(Foreground, GlyphRunText.Create(latLabel, Typeface, FontSize, latPos));
drawingContext.DrawGlyphRun(Foreground, GlyphRunText.Create(lonLabel, Typeface, FontSize, lonPos));
drawingContext.Pop();

View file

@ -13,7 +13,7 @@ namespace MapControl
/// <summary>
/// Draws a graticule overlay.
/// </summary>
public partial class MapGraticule : MapOverlay
public partial class MapGraticule
{
/// <summary>
/// Graticule line spacings in degrees.
@ -24,11 +24,6 @@ namespace MapControl
public static readonly DependencyProperty MinLineSpacingProperty = DependencyProperty.Register(
"MinLineSpacing", typeof(double), typeof(MapGraticule), new PropertyMetadata(150d));
public MapGraticule()
{
StrokeThickness = 0.5;
}
/// <summary>
/// Minimum spacing in pixels between adjacent graticule lines.
/// </summary>

41
MapControl/MapImage.cs Normal file
View file

@ -0,0 +1,41 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
#else
using System.Windows;
using System.Windows.Media;
#endif
namespace MapControl
{
public class MapImage : MapRectangle
{
private static readonly Transform imageTransform = new MatrixTransform
{
Matrix = new Matrix(1, 0, 0, -1, 0, 1)
};
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(ImageSource), typeof(MapImage),
new PropertyMetadata(null, (o, e) => ((MapImage)o).SourceChanged((ImageSource)e.NewValue)));
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
private void SourceChanged(ImageSource source)
{
Fill = new ImageBrush
{
ImageSource = source,
RelativeTransform = imageTransform
};
}
}
}

View file

@ -15,8 +15,7 @@ namespace MapControl
public class MapItem : ListBoxItem
{
public static readonly DependencyProperty IsCurrentProperty = MapItemsControl.IsCurrentProperty.AddOwner(
typeof(MapItem),
new PropertyMetadata((o, e) => ((MapItem)o).IsCurrentPropertyChanged((bool)e.NewValue)));
typeof(MapItem), new PropertyMetadata((o, e) => ((MapItem)o).IsCurrentPropertyChanged((bool)e.NewValue)));
static MapItem()
{

View file

@ -1,129 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI;
using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
#else
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
#endif
namespace MapControl
{
public partial class MapOverlay : MapPanel
{
public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register(
"FontFamily", typeof(FontFamily), typeof(MapOverlay),
new PropertyMetadata(default(FontFamily), (o, e) => ((MapOverlay)o).FontSizePropertyChanged()));
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
"FontSize", typeof(double), typeof(MapOverlay),
new PropertyMetadata(10d, (o, e) => ((MapOverlay)o).FontSizePropertyChanged()));
public static readonly DependencyProperty FontStyleProperty = DependencyProperty.Register(
"FontStyle", typeof(FontStyle), typeof(MapOverlay),
new PropertyMetadata(default(FontStyle), (o, e) => ((MapOverlay)o).FontSizePropertyChanged()));
public static readonly DependencyProperty FontStretchProperty = DependencyProperty.Register(
"FontStretch", typeof(FontStretch), typeof(MapOverlay),
new PropertyMetadata(default(FontStretch), (o, e) => ((MapOverlay)o).FontSizePropertyChanged()));
public static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register(
"FontWeight", typeof(FontWeight), typeof(MapOverlay),
new PropertyMetadata(FontWeights.Normal, (o, e) => ((MapOverlay)o).FontSizePropertyChanged()));
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
"Foreground", typeof(Brush), typeof(MapOverlay),
new PropertyMetadata(new SolidColorBrush(Colors.Black), (o, e) => ((MapOverlay)o).ForegroundPropertyChanged()));
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
"Stroke", typeof(Brush), typeof(MapOverlay),
new PropertyMetadata(new SolidColorBrush(Colors.Black), (o, e) => ((MapOverlay)o).Path.Stroke = (Brush)e.NewValue));
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
"StrokeThickness", typeof(double), typeof(MapOverlay),
new PropertyMetadata(1d, (o, e) => ((MapOverlay)o).StrokeThicknessPropertyChanged((double)e.NewValue)));
public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register(
"StrokeDashArray", typeof(DoubleCollection), typeof(MapOverlay),
new PropertyMetadata(null, (o, e) => ((MapOverlay)o).Path.StrokeDashArray = (DoubleCollection)e.NewValue));
public static readonly DependencyProperty StrokeDashOffsetProperty = DependencyProperty.Register(
"StrokeDashOffset", typeof(double), typeof(MapOverlay),
new PropertyMetadata(0d, (o, e) => ((MapOverlay)o).Path.StrokeDashOffset = (double)e.NewValue));
public static readonly DependencyProperty StrokeDashCapProperty = DependencyProperty.Register(
"StrokeDashCap", typeof(PenLineCap), typeof(MapOverlay),
new PropertyMetadata(default(PenLineCap), (o, e) => ((MapOverlay)o).Path.StrokeDashCap = (PenLineCap)e.NewValue));
public static readonly DependencyProperty StrokeStartLineCapProperty = DependencyProperty.Register(
"StrokeStartLineCap", typeof(PenLineCap), typeof(MapOverlay),
new PropertyMetadata(default(PenLineCap), (o, e) => ((MapOverlay)o).Path.StrokeStartLineCap = (PenLineCap)e.NewValue));
public static readonly DependencyProperty StrokeEndLineCapProperty = DependencyProperty.Register(
"StrokeEndLineCap", typeof(PenLineCap), typeof(MapOverlay),
new PropertyMetadata(default(PenLineCap), (o, e) => ((MapOverlay)o).Path.StrokeEndLineCap = (PenLineCap)e.NewValue));
public static readonly DependencyProperty StrokeLineJoinProperty = DependencyProperty.Register(
"StrokeLineJoin", typeof(PenLineJoin), typeof(MapOverlay),
new PropertyMetadata(default(PenLineJoin), (o, e) => ((MapOverlay)o).Path.StrokeLineJoin = (PenLineJoin)e.NewValue));
public static readonly DependencyProperty StrokeMiterLimitProperty = DependencyProperty.Register(
"StrokeMiterLimit", typeof(double), typeof(MapOverlay),
new PropertyMetadata(1d, (o, e) => ((MapOverlay)o).Path.StrokeMiterLimit = (double)e.NewValue));
protected readonly Path Path = new Path();
protected readonly PathGeometry Geometry = new PathGeometry();
public MapOverlay()
{
IsHitTestVisible = false;
Path.Stroke = Stroke;
Path.StrokeThickness = StrokeThickness;
Path.StrokeDashArray = StrokeDashArray;
Path.StrokeDashOffset = StrokeDashOffset;
Path.StrokeDashCap = StrokeDashCap;
Path.StrokeStartLineCap = StrokeStartLineCap;
Path.StrokeEndLineCap = StrokeEndLineCap;
Path.StrokeLineJoin = StrokeLineJoin;
Path.StrokeMiterLimit = StrokeMiterLimit;
Path.Data = Geometry;
Children.Add(Path);
}
private void FontSizePropertyChanged()
{
if (GetParentMap(this) != null)
{
// FontSize may affect layout
OnViewportChanged();
}
}
private void ForegroundPropertyChanged()
{
if (GetParentMap(this) != null)
{
// Foreground may affect rendering
OnViewportChanged();
}
}
private void StrokeThicknessPropertyChanged(double thickness)
{
Path.StrokeThickness = thickness;
if (GetParentMap(this) != null)
{
// StrokeThickness may affect layout
OnViewportChanged();
}
}
}
}

View file

@ -1,151 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace MapControl
{
public partial class MapOverlay : FrameworkElement, IMapElement
{
public static readonly DependencyProperty BackgroundProperty = Control.BackgroundProperty.AddOwner(
typeof(MapOverlay));
public static readonly DependencyProperty FontSizeProperty = Control.FontSizeProperty.AddOwner(
typeof(MapOverlay));
public static readonly DependencyProperty FontFamilyProperty = Control.FontFamilyProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty FontStyleProperty = Control.FontStyleProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty FontStretchProperty = Control.FontStretchProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty FontWeightProperty = Control.FontWeightProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty ForegroundProperty = Control.ForegroundProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).ForegroundChanged((Brush)e.NewValue)));
public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.Brush = (Brush)e.NewValue));
public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => ((MapOverlay)o).pen.Thickness = (double)e.NewValue));
public static readonly DependencyProperty StrokeDashArrayProperty = Shape.StrokeDashArrayProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.DashStyle = new DashStyle((DoubleCollection)e.NewValue, ((MapOverlay)o).StrokeDashOffset)));
public static readonly DependencyProperty StrokeDashOffsetProperty = Shape.StrokeDashOffsetProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.DashStyle = new DashStyle(((MapOverlay)o).StrokeDashArray, (double)e.NewValue)));
public static readonly DependencyProperty StrokeDashCapProperty = Shape.StrokeDashCapProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.DashCap = (PenLineCap)e.NewValue));
public static readonly DependencyProperty StrokeStartLineCapProperty = Shape.StrokeStartLineCapProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.StartLineCap = (PenLineCap)e.NewValue));
public static readonly DependencyProperty StrokeEndLineCapProperty = Shape.StrokeEndLineCapProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.EndLineCap = (PenLineCap)e.NewValue));
public static readonly DependencyProperty StrokeLineJoinProperty = Shape.StrokeLineJoinProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.LineJoin = (PenLineJoin)e.NewValue));
public static readonly DependencyProperty StrokeMiterLimitProperty = Shape.StrokeMiterLimitProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen.MiterLimit = (double)e.NewValue));
private Pen pen;
private Typeface typeface;
static MapOverlay()
{
UIElement.IsHitTestVisibleProperty.OverrideMetadata(
typeof(MapOverlay), new FrameworkPropertyMetadata(false));
}
public MapOverlay()
{
pen = new Pen
{
Brush = Stroke,
Thickness = StrokeThickness,
DashStyle = new DashStyle(StrokeDashArray, StrokeDashOffset),
DashCap = StrokeDashCap,
StartLineCap = StrokeStartLineCap,
EndLineCap = StrokeEndLineCap,
LineJoin = StrokeLineJoin,
MiterLimit = StrokeMiterLimit
};
}
public Brush Background
{
get { return (Brush)GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
protected Pen Pen
{
get
{
if (pen.Brush == null)
{
pen.Brush = Foreground;
}
return pen;
}
}
protected Typeface Typeface
{
get
{
if (typeface == null)
{
typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
}
return typeface;
}
}
protected virtual void OnViewportChanged()
{
InvalidateVisual();
}
private void OnViewportChanged(object sender, EventArgs e)
{
OnViewportChanged();
}
void IMapElement.ParentMapChanged(MapBase oldParentMap, MapBase newParentMap)
{
if (oldParentMap != null)
{
oldParentMap.ViewportChanged -= OnViewportChanged;
}
if (newParentMap != null)
{
newParentMap.ViewportChanged += OnViewportChanged;
OnViewportChanged();
}
}
private void ForegroundChanged(Brush foreground)
{
if (Stroke == null)
{
pen.Brush = foreground;
}
}
}
}

View file

@ -2,26 +2,70 @@
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI.Text;
using Windows.UI.Xaml.Media;
#else
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
#endif
using System.Windows.Shapes;
namespace MapControl
{
/// <summary>
/// Base class for map overlays with font, background, foreground and stroke properties.
/// Rendering is typically done by overriding OnRender in derived classes.
/// </summary>
public partial class MapOverlay
public class MapOverlay : FrameworkElement, IMapElement
{
public FontFamily FontFamily
{
get { return (FontFamily)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
public static readonly DependencyProperty FontSizeProperty = Control.FontSizeProperty.AddOwner(
typeof(MapOverlay));
public static readonly DependencyProperty FontFamilyProperty = Control.FontFamilyProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty FontStyleProperty = Control.FontStyleProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty FontStretchProperty = Control.FontStretchProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty FontWeightProperty = Control.FontWeightProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
public static readonly DependencyProperty BackgroundProperty = Control.BackgroundProperty.AddOwner(
typeof(MapOverlay));
public static readonly DependencyProperty ForegroundProperty = Control.ForegroundProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).ForegroundChanged()));
public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeDashArrayProperty = Shape.StrokeDashArrayProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeDashOffsetProperty = Shape.StrokeDashOffsetProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeDashCapProperty = Shape.StrokeDashCapProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineCap), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeStartLineCapProperty = Shape.StrokeStartLineCapProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineCap), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeEndLineCapProperty = Shape.StrokeEndLineCapProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineCap), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeLineJoinProperty = Shape.StrokeLineJoinProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineJoin), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
public static readonly DependencyProperty StrokeMiterLimitProperty = Shape.StrokeMiterLimitProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
private MapBase parentMap;
private Typeface typeface;
private Pen pen;
public double FontSize
{
@ -29,6 +73,12 @@ namespace MapControl
set { SetValue(FontSizeProperty, value); }
}
public FontFamily FontFamily
{
get { return (FontFamily)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
public FontStyle FontStyle
{
get { return (FontStyle)GetValue(FontStyleProperty); }
@ -47,6 +97,12 @@ namespace MapControl
set { SetValue(FontWeightProperty, value); }
}
public Brush Background
{
get { return (Brush)GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
public Brush Foreground
{
get { return (Brush)GetValue(ForegroundProperty); }
@ -106,5 +162,75 @@ namespace MapControl
get { return (double)GetValue(StrokeMiterLimitProperty); }
set { SetValue(StrokeMiterLimitProperty, value); }
}
public MapBase ParentMap
{
get { return parentMap; }
set
{
if (parentMap != null)
{
parentMap.ViewportChanged -= (o, e) => OnViewportChanged();
}
parentMap = value;
if (parentMap != null)
{
parentMap.ViewportChanged += (o, e) => OnViewportChanged();
OnViewportChanged();
}
}
}
protected Typeface Typeface
{
get
{
if (typeface == null)
{
typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
}
return typeface;
}
}
protected Pen Pen
{
get
{
if (pen == null)
{
pen = new Pen
{
Brush = Stroke != null ? Stroke : Foreground,
Thickness = StrokeThickness,
DashStyle = new DashStyle(StrokeDashArray, StrokeDashOffset),
DashCap = StrokeDashCap,
StartLineCap = StrokeStartLineCap,
EndLineCap = StrokeEndLineCap,
LineJoin = StrokeLineJoin,
MiterLimit = StrokeMiterLimit
};
pen.Freeze();
}
return pen;
}
}
protected virtual void OnViewportChanged()
{
}
private void ForegroundChanged()
{
if (Stroke == null)
{
pen = null;
}
}
}
}

View file

@ -72,5 +72,10 @@ namespace MapControl
return parentMap;
}
internal void SetParentMap()
{
SetValue(ParentMapProperty, this);
}
}
}

View file

@ -8,13 +8,20 @@ namespace MapControl
{
public partial class MapPanel
{
public static readonly DependencyProperty ParentMapProperty = DependencyProperty.RegisterAttached(
private static readonly DependencyPropertyKey ParentMapPropertyKey = DependencyProperty.RegisterAttachedReadOnly(
"ParentMap", typeof(MapBase), typeof(MapPanel),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, ParentMapPropertyChanged));
public static readonly DependencyProperty ParentMapProperty = ParentMapPropertyKey.DependencyProperty;
public static MapBase GetParentMap(UIElement element)
{
return (MapBase)element.GetValue(ParentMapProperty);
}
internal void SetParentMap()
{
SetValue(ParentMapPropertyKey, this);
}
}
}

View file

@ -18,7 +18,7 @@ namespace MapControl
{
internal interface IMapElement
{
void ParentMapChanged(MapBase oldParentMap, MapBase newParentMap);
MapBase ParentMap { get; set; }
}
/// <summary>
@ -49,6 +49,41 @@ namespace MapControl
return (Point?)element.GetValue(ViewportPositionProperty);
}
private MapBase parentMap;
public MapBase ParentMap
{
get { return parentMap; }
set
{
if (parentMap != null && parentMap != this)
{
parentMap.ViewportChanged -= (o, e) => OnViewportChanged();
}
parentMap = value;
if (parentMap != null && parentMap != this)
{
parentMap.ViewportChanged += (o, e) => OnViewportChanged();
OnViewportChanged();
}
}
}
protected virtual void OnViewportChanged()
{
foreach (UIElement element in InternalChildren)
{
var location = GetLocation(element);
if (location != null)
{
SetViewportPosition(element, parentMap, location);
}
}
}
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement element in InternalChildren)
@ -61,8 +96,6 @@ namespace MapControl
protected override Size ArrangeOverride(Size finalSize)
{
var parentMap = GetParentMap(this);
foreach (UIElement element in InternalChildren)
{
var rect = new Rect(0d, 0d, element.DesiredSize.Width, element.DesiredSize.Height);
@ -92,47 +125,13 @@ namespace MapControl
return finalSize;
}
protected virtual void OnViewportChanged()
{
var parentMap = GetParentMap(this);
foreach (UIElement element in InternalChildren)
{
var location = GetLocation(element);
if (location != null)
{
SetViewportPosition(element, parentMap, location);
}
}
}
private void OnViewportChanged(object sender, EventArgs e)
{
OnViewportChanged();
}
void IMapElement.ParentMapChanged(MapBase oldParentMap, MapBase newParentMap)
{
if (oldParentMap != null && oldParentMap != this)
{
oldParentMap.ViewportChanged -= OnViewportChanged;
}
if (newParentMap != null && newParentMap != this)
{
newParentMap.ViewportChanged += OnViewportChanged;
OnViewportChanged();
}
}
private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var element = obj as IMapElement;
var mapElement = obj as IMapElement;
if (element != null)
if (mapElement != null)
{
element.ParentMapChanged(e.OldValue as MapBase, e.NewValue as MapBase);
mapElement.ParentMap = e.NewValue as MapBase;
}
}
@ -142,7 +141,10 @@ namespace MapControl
if (element != null)
{
SetViewportPosition(element, GetParentMap(element), (Location)e.NewValue);
var mapElement = element as IMapElement;
var parentMap = mapElement != null ? mapElement.ParentMap : GetParentMap(element);
SetViewportPosition(element, parentMap, (Location)e.NewValue);
}
}

View file

@ -5,38 +5,31 @@
using System.Linq;
#if NETFX_CORE
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
#else
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
#endif
namespace MapControl
{
public partial class MapPolyline : Path
public partial class MapPolyline
{
protected readonly PathGeometry Geometry = new PathGeometry();
public MapPolyline()
: base(new PathGeometry())
{
Data = Geometry;
MapPanel.AddParentMapHandlers(this);
}
private void UpdateGeometry()
protected override void UpdateGeometry()
{
var parentMap = MapPanel.GetParentMap(this);
var geometry = (PathGeometry)Geometry;
var locations = Locations;
Location first;
Geometry.Figures.Clear();
if (parentMap != null && locations != null && (first = locations.FirstOrDefault()) != null)
if (ParentMap != null && locations != null && (first = locations.FirstOrDefault()) != null)
{
var figure = new PathFigure
{
StartPoint = parentMap.MapTransform.Transform(first),
StartPoint = ParentMap.MapTransform.Transform(first),
IsClosed = IsClosed,
IsFilled = IsClosed
};
@ -45,7 +38,7 @@ namespace MapControl
foreach (var location in locations.Skip(1))
{
segment.Points.Add(parentMap.MapTransform.Transform(location));
segment.Points.Add(ParentMap.MapTransform.Transform(location));
}
if (segment.Points.Count > 0)
@ -53,12 +46,14 @@ namespace MapControl
figure.Segments.Add(segment);
}
Geometry.Figures.Add(figure);
Geometry.Transform = parentMap.ViewportTransform;
geometry.Figures.Clear();
geometry.Figures.Add(figure);
geometry.Transform = ParentMap.ViewportTransform;
}
else
{
Geometry.Transform = null;
geometry.Figures.Clear();
geometry.ClearValue(Geometry.TransformProperty);
}
}
}

View file

@ -4,42 +4,39 @@
using System.Linq;
using System.Windows.Media;
using System.Windows.Shapes;
namespace MapControl
{
public partial class MapPolyline : Shape
public partial class MapPolyline
{
protected readonly StreamGeometry Geometry = new StreamGeometry();
protected override Geometry DefiningGeometry
public MapPolyline()
: base(new StreamGeometry())
{
get { return Geometry; }
}
private void UpdateGeometry()
protected override void UpdateGeometry()
{
var parentMap = MapPanel.GetParentMap(this);
var geometry = (StreamGeometry)Geometry;
var locations = Locations;
Location first;
if (parentMap != null && locations != null && (first = locations.FirstOrDefault()) != null)
if (ParentMap != null && locations != null && (first = locations.FirstOrDefault()) != null)
{
using (var context = Geometry.Open())
using (var context = geometry.Open())
{
var startPoint = parentMap.MapTransform.Transform(first);
var points = locations.Skip(1).Select(l => parentMap.MapTransform.Transform(l)).ToList();
var startPoint = ParentMap.MapTransform.Transform(first);
var points = locations.Skip(1).Select(l => ParentMap.MapTransform.Transform(l)).ToList();
context.BeginFigure(startPoint, IsClosed, IsClosed);
context.PolyLineTo(points, true, false);
}
Geometry.Transform = parentMap.ViewportTransform;
geometry.Transform = ParentMap.ViewportTransform;
}
else
{
Geometry.Clear();
Geometry.Transform = null;
geometry.Clear();
geometry.ClearValue(Geometry.TransformProperty);
}
}
}

View file

@ -14,7 +14,7 @@ using System.Windows;
namespace MapControl
{
public partial class MapPolyline : IMapElement
public partial class MapPolyline : MapShape
{
#if NETFX_CORE
// For WinRT, the Locations dependency property type is declared as object
@ -49,21 +49,6 @@ namespace MapControl
set { SetValue(IsClosedProperty, value); }
}
protected override Size MeasureOverride(Size constraint)
{
// Shape.MeasureOverride in WPF and WinRT sometimes return a Size with zero
// width or height, whereas Shape.MeasureOverride in Silverlight occasionally
// throws an ArgumentException, as it tries to create a Size from a negative
// width or height, apparently resulting from a transformed geometry in Path.Data.
// In either case it seems to be sufficient to simply return a non-zero size.
return new Size(1, 1);
}
void IMapElement.ParentMapChanged(MapBase oldParentMap, MapBase newParentMap)
{
UpdateGeometry();
}
private void LocationCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateGeometry();

100
MapControl/MapRectangle.cs Normal file
View file

@ -0,0 +1,100 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
#else
using System.Windows;
using System.Windows.Media;
#endif
namespace MapControl
{
public partial class MapRectangle : MapShape
{
private static Transform DefaultFillRelativeTransform =
Brush.RelativeTransformProperty.GetMetadata(typeof(Brush)).DefaultValue as Transform;
public static readonly DependencyProperty SouthProperty = DependencyProperty.Register(
"South", typeof(double), typeof(MapRectangle),
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateGeometry()));
public static readonly DependencyProperty NorthProperty = DependencyProperty.Register(
"North", typeof(double), typeof(MapRectangle),
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateGeometry()));
public static readonly DependencyProperty WestProperty = DependencyProperty.Register(
"West", typeof(double), typeof(MapRectangle),
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateGeometry()));
public static readonly DependencyProperty EastProperty = DependencyProperty.Register(
"East", typeof(double), typeof(MapRectangle),
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateGeometry()));
public MapRectangle()
: base(new RectangleGeometry())
{
}
public double South
{
get { return (double)GetValue(SouthProperty); }
set { SetValue(SouthProperty, value); }
}
public double North
{
get { return (double)GetValue(NorthProperty); }
set { SetValue(NorthProperty, value); }
}
public double West
{
get { return (double)GetValue(WestProperty); }
set { SetValue(WestProperty, value); }
}
public double East
{
get { return (double)GetValue(EastProperty); }
set { SetValue(EastProperty, value); }
}
protected override void UpdateGeometry()
{
var geometry = (RectangleGeometry)Geometry;
if (ParentMap != null &&
!double.IsNaN(South) && !double.IsNaN(North) &&
!double.IsNaN(West) && !double.IsNaN(East) &&
South < North && West < East)
{
var p1 = ParentMap.MapTransform.Transform(new Location(South, West));
var p2 = ParentMap.MapTransform.Transform(new Location(North, East));
geometry.Rect = new Rect(p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y);
RenderTransform = ParentMap.ViewportTransform;
}
else
{
geometry.Rect = Rect.Empty;
ClearValue(RenderTransformProperty);
}
}
//#if !NETFX_CORE && !SILVERLIGHT
// protected override void OnRender(DrawingContext drawingContext)
// {
// if (ParentMap != null)
// {
// drawingContext.PushTransform(ParentMap.ViewportTransform);
// drawingContext.DrawRectangle(Fill, null, ((RectangleGeometry)Geometry).Rect);
// drawingContext.Pop();
// }
// }
//#endif
}
}

View file

@ -15,13 +15,16 @@ namespace MapControl
public class MapScale : MapOverlay
{
public static readonly DependencyProperty PaddingProperty = Control.PaddingProperty.AddOwner(
typeof(MapOverlay), new FrameworkPropertyMetadata(new Thickness(2d)));
typeof(MapScale), new FrameworkPropertyMetadata(new Thickness(2d)));
private double length;
private Size size;
static MapScale()
{
UIElement.IsHitTestVisibleProperty.OverrideMetadata(
typeof(MapScale), new FrameworkPropertyMetadata(false));
FrameworkElement.MinWidthProperty.OverrideMetadata(
typeof(MapScale), new FrameworkPropertyMetadata(100d));
@ -46,11 +49,9 @@ namespace MapControl
protected override Size MeasureOverride(Size availableSize)
{
var parentMap = MapPanel.GetParentMap(this);
if (parentMap != null && parentMap.CenterScale > 0d)
if (ParentMap != null && ParentMap.CenterScale > 0d)
{
length = MinWidth / parentMap.CenterScale;
length = MinWidth / ParentMap.CenterScale;
var magnitude = Math.Pow(10d, Math.Floor(Math.Log10(length)));
if (length / magnitude < 2d)
@ -66,7 +67,7 @@ namespace MapControl
length = 10d * magnitude;
}
size.Width = length * parentMap.CenterScale + StrokeThickness + Padding.Left + Padding.Right;
size.Width = length * ParentMap.CenterScale + StrokeThickness + Padding.Left + Padding.Right;
size.Height = FontSize + 2d * StrokeThickness + Padding.Top + Padding.Bottom;
}
else
@ -79,9 +80,7 @@ namespace MapControl
protected override void OnRender(DrawingContext drawingContext)
{
var parentMap = MapPanel.GetParentMap(this);
if (parentMap != null)
if (ParentMap != null)
{
var x1 = Padding.Left + StrokeThickness / 2d;
var x2 = size.Width - Padding.Right - StrokeThickness / 2d;
@ -89,7 +88,7 @@ namespace MapControl
var y2 = size.Height - Padding.Bottom - StrokeThickness / 2d;
var text = length >= 1000d ? string.Format("{0:0} km", length / 1000d) : string.Format("{0:0} m", length);
drawingContext.DrawRectangle(Background ?? parentMap.Background, null, new Rect(size));
drawingContext.DrawRectangle(Background ?? ParentMap.Background, null, new Rect(size));
drawingContext.DrawLine(Pen, new Point(x1, y1), new Point(x1, y2));
drawingContext.DrawLine(Pen, new Point(x2, y1), new Point(x2, y2));
drawingContext.DrawLine(Pen, new Point(x1, y2), new Point(x2, y2));

View file

@ -0,0 +1,23 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
#else
using System.Windows.Media;
using System.Windows.Shapes;
#endif
namespace MapControl
{
public partial class MapShape : Path
{
public MapShape(Geometry geometry)
{
Data = Geometry = geometry;
MapPanel.AddParentMapHandlers(this);
}
}
}

View file

@ -0,0 +1,22 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows.Media;
using System.Windows.Shapes;
namespace MapControl
{
public partial class MapShape : Shape
{
public MapShape(Geometry geometry)
{
Geometry = geometry;
}
protected override Geometry DefiningGeometry
{
get { return Geometry; }
}
}
}

49
MapControl/MapShape.cs Normal file
View file

@ -0,0 +1,49 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.Foundation;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
#else
using System.Windows;
using System.Windows.Media;
#endif
namespace MapControl
{
/// <summary>
/// Base class for map shapes.
/// </summary>
public partial class MapShape : IMapElement
{
private MapBase parentMap;
public MapBase ParentMap
{
get { return parentMap; }
set
{
parentMap = value;
UpdateGeometry();
}
}
protected readonly Geometry Geometry;
protected virtual void UpdateGeometry()
{
}
protected override Size MeasureOverride(Size constraint)
{
// Shape.MeasureOverride in WPF and WinRT sometimes return a Size with zero
// width or height, whereas Shape.MeasureOverride in Silverlight occasionally
// throws an ArgumentException, as it tries to create a Size from a negative
// width or height, apparently resulting from a transformed Geometry.
// In either case it seems to be sufficient to simply return a non-zero size.
return new Size(1, 1);
}
}
}

View file

@ -16,6 +16,6 @@ using System.Windows;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]

View file

@ -63,6 +63,9 @@
<Compile Include="..\MapGraticule.Silverlight.WinRT.cs">
<Link>MapGraticule.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapImage.cs">
<Link>MapImage.cs</Link>
</Compile>
<Compile Include="..\MapItem.Silverlight.WinRT.cs">
<Link>MapItem.Silverlight.WinRT.cs</Link>
</Compile>
@ -72,12 +75,6 @@
<Compile Include="..\MapItemsControl.Silverlight.WinRT.cs">
<Link>MapItemsControl.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapOverlay.cs">
<Link>MapOverlay.cs</Link>
</Compile>
<Compile Include="..\MapOverlay.Silverlight.WinRT.cs">
<Link>MapOverlay.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapPanel.cs">
<Link>MapPanel.cs</Link>
</Compile>
@ -90,6 +87,15 @@
<Compile Include="..\MapPolyline.Silverlight.WinRT.cs">
<Link>MapPolyline.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapRectangle.cs">
<Link>MapRectangle.cs</Link>
</Compile>
<Compile Include="..\MapShape.cs">
<Link>MapShape.cs</Link>
</Compile>
<Compile Include="..\MapShape.Silverlight.WinRT.cs">
<Link>MapShape.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapTransform.cs">
<Link>MapTransform.cs</Link>
</Compile>

View file

@ -9,6 +9,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]

View file

@ -9,6 +9,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -105,6 +105,8 @@
</Grid.RowDefinitions>
<map:Map x:Name="map" Center="53.5,8.2" MinZoomLevel="2" MaxZoomLevel="18" ZoomLevel="11"
MouseMove="MapMouseMove" MouseLeave="MapMouseLeave">
<map:MapImage x:Name="mapImage" South="53.54031" North="53.74871" West="8.08594" East="8.43750"
Source="10_535_330.jpg" Opacity=".5"/>
<map:MapGraticule Opacity="0.6"/>
<!-- use ItemTemplate or ItemContainerStyle alternatively -->
@ -136,16 +138,27 @@
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Name="mouseLocation" Margin="4" VerticalAlignment="Center"/>
<TextBlock Name="mouseLocation" Margin="4" VerticalAlignment="Bottom" FontFamily="Consolas"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Slider Margin="4" Width="100" SmallChange="0.01"
Maximum="{Binding MaxZoomLevel, ElementName=map}"
Minimum="{Binding MinZoomLevel, ElementName=map}"
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
<Slider Margin="4" Width="100" Minimum="0" Maximum="360" SmallChange="5" LargeChange="45"
Value="{Binding TargetHeading, ElementName=map, Mode=TwoWay}"/>
<CheckBox Margin="4" VerticalAlignment="Center" Content="Seamarks" Click="SeamarksClick"/>
<ComboBox Margin="4" Width="120" SelectedIndex="0" SelectionChanged="TileLayerSelectionChanged">
<StackPanel Margin="5">
<TextBlock Text="Zoom Level" Margin="0,0,0,2" HorizontalAlignment="Center" Foreground="Gray" FontSize="10"/>
<Slider Width="100" SmallChange="0.01"
Maximum="{Binding MaxZoomLevel, ElementName=map}"
Minimum="{Binding MinZoomLevel, ElementName=map}"
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Margin="5">
<TextBlock Text="Heading" Margin="0,0,0,2" HorizontalAlignment="Center" Foreground="Gray" FontSize="10"/>
<Slider Width="100" SmallChange="5" LargeChange="45" Minimum="0" Maximum="360"
Value="{Binding TargetHeading, ElementName=map, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Margin="5">
<TextBlock Text="Image Opacity" Margin="0,0,0,2" HorizontalAlignment="Center" Foreground="Gray" FontSize="10"/>
<Slider Width="100" Minimum="0" Maximum="1"
Value="{Binding Opacity, ElementName=mapImage, Mode=TwoWay}"/>
</StackPanel>
<CheckBox Margin="5" VerticalAlignment="Bottom" Content="Seamarks" Click="SeamarksClick"/>
<ComboBox Margin="5" VerticalAlignment="Bottom" Width="120" SelectedIndex="0" SelectionChanged="TileLayerSelectionChanged">
<sys:String>OpenStreetMap</sys:String>
<sys:String>OpenCycleMap</sys:String>
<sys:String>OCM Transport</sys:String>

View file

@ -1,6 +1,7 @@
using MapControl;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
@ -20,7 +21,7 @@ namespace SilverlightApplication
{
InitializeComponent();
ICollection<object> polylines = (ICollection<object>)Resources["Polylines"];
var polylines = (ICollection<object>)Resources["Polylines"];
polylines.Add(
new SamplePolyline
{
@ -32,7 +33,7 @@ namespace SilverlightApplication
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")
});
ICollection<object> points = (ICollection<object>)Resources["Points"];
var points = (ICollection<object>)Resources["Points"];
points.Add(
new SamplePoint
{
@ -71,7 +72,7 @@ namespace SilverlightApplication
});
points.Add(movingPoint);
ICollection<object> pushpins = (ICollection<object>)Resources["Pushpins"];
var pushpins = (ICollection<object>)Resources["Pushpins"];
pushpins.Add(
new SamplePoint
{
@ -97,8 +98,7 @@ namespace SilverlightApplication
Location = new Location(53.5207, 8.2323)
});
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(0.1);
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.1) };
timer.Tick += MovePoint;
timer.Start();
}
@ -121,7 +121,15 @@ namespace SilverlightApplication
private void MapMouseMove(object sender, MouseEventArgs e)
{
mouseLocation.Text = map.ViewportPointToLocation(e.GetPosition(map)).ToString();
var location = map.ViewportPointToLocation(e.GetPosition(map));
var longitude = Location.NormalizeLongitude(location.Longitude);
var latString = location.Latitude < 0 ?
string.Format(CultureInfo.InvariantCulture, "S {0:00.00000}", -location.Latitude) :
string.Format(CultureInfo.InvariantCulture, "N {0:00.00000}", location.Latitude);
var lonString = longitude < 0 ?
string.Format(CultureInfo.InvariantCulture, "W {0:000.00000}", -longitude) :
string.Format(CultureInfo.InvariantCulture, "E {0:000.00000}", longitude);
mouseLocation.Text = latString + "\n" + lonString;
}
private void TileLayerSelectionChanged(object sender, SelectionChangedEventArgs e)

View file

@ -9,6 +9,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]

View file

@ -107,6 +107,9 @@
<Name>MapControl.Silverlight</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="10_535_330.jpg" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -107,6 +107,8 @@
<map:MapBase.Center>
<map:Location Latitude="53.5" Longitude="8.2"/>
</map:MapBase.Center>
<map:MapImage x:Name="mapImage" South="53.54031" North="53.74871" West="8.08594" East="8.43750"
Source="10_535_330.jpg" Opacity=".5"/>
<map:MapGraticule Foreground="Black" Opacity="0.6"/>
<!-- use ItemTemplate or ItemContainerStyle alternatively -->
@ -145,16 +147,25 @@
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Name="mouseLocation" Margin="4" VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Slider Margin="10,0,10,0" Width="200" SmallChange="0.1"
Minimum="{Binding MinZoomLevel, ElementName=map}"
Maximum="{Binding MaxZoomLevel, ElementName=map}"
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
<Slider Margin="10,0,10,0" Width="200" Minimum="0" Maximum="360" SmallChange="5" LargeChange="45"
Value="{Binding Heading, ElementName=map, Mode=TwoWay}"/>
<StackPanel Margin="5">
<TextBlock Text="Zoom Level" HorizontalAlignment="Center" Foreground="Gray" FontSize="14"/>
<Slider Margin="10,-10,10,-10" Width="200" SmallChange="0.1"
Minimum="{Binding MinZoomLevel, ElementName=map}"
Maximum="{Binding MaxZoomLevel, ElementName=map}"
Value="{Binding TargetZoomLevel, ElementName=map, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Margin="5">
<TextBlock Text="Heading" HorizontalAlignment="Center" Foreground="Gray" FontSize="14"/>
<Slider Margin="10,-10,10,-10" Width="200" Minimum="0" Maximum="360" SmallChange="5" LargeChange="45"
Value="{Binding Heading, ElementName=map, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Margin="5">
<TextBlock Text="Image Opacity" HorizontalAlignment="Center" Foreground="Gray" FontSize="14"/>
<Slider Margin="10,-10,10,-10" Width="200" Value="50" ValueChanged="ImageOpacitySliderValueChanged"/>
</StackPanel>
<CheckBox Margin="10" VerticalAlignment="Center" Content="Seamarks" Click="SeamarksClick"/>
<ComboBox Margin="10" Width="200" SelectedIndex="0" SelectionChanged="TileLayerSelectionChanged">
<ComboBox Margin="10" Width="200" VerticalAlignment="Center" SelectedIndex="0" SelectionChanged="TileLayerSelectionChanged">
<ComboBoxItem>OpenStreetMap</ComboBoxItem>
<ComboBoxItem>OpenCycleMap</ComboBoxItem>
<ComboBoxItem>OCM Transport</ComboBoxItem>

View file

@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Controls.Primitives;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
@ -24,7 +24,7 @@ namespace StoreApplication
{
this.InitializeComponent();
ICollection<object> polylines = (ICollection<object>)Resources["Polylines"];
var polylines = (ICollection<object>)Resources["Polylines"];
polylines.Add(
new SamplePolyline
{
@ -36,7 +36,7 @@ namespace StoreApplication
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")
});
ICollection<object> points = (ICollection<object>)Resources["Points"];
var points = (ICollection<object>)Resources["Points"];
points.Add(
new SamplePoint
{
@ -75,7 +75,7 @@ namespace StoreApplication
});
points.Add(movingPoint);
ICollection<object> pushpins = (ICollection<object>)Resources["Pushpins"];
var pushpins = (ICollection<object>)Resources["Pushpins"];
pushpins.Add(
new SamplePoint
{
@ -101,8 +101,7 @@ namespace StoreApplication
Location = new Location(53.5207, 8.2323)
});
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(0.1);
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.1) };
timer.Tick += MovePoint;
timer.Start();
}
@ -118,13 +117,12 @@ namespace StoreApplication
}
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
private void ImageOpacitySliderValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (mapImage != null)
{
mapImage.Opacity = e.NewValue / 100;
}
}
private void SeamarksClick(object sender, RoutedEventArgs e)

View file

@ -9,6 +9,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]

View file

@ -50,6 +50,7 @@
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="10_535_330.jpg" />
<Content Include="Assets\Logo.png" />
<Content Include="Assets\SmallLogo.png" />
<Content Include="Assets\SplashScreen.png" />

View file

@ -10,7 +10,7 @@ using System.Windows;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -155,6 +155,8 @@
MouseLeftButtonDown="MapMouseLeftButtonDown" MouseRightButtonDown="MapMouseRightButtonDown"
MouseMove="MapMouseMove" MouseLeave="MapMouseLeave"
ManipulationInertiaStarting="MapManipulationInertiaStarting">
<map:MapImage x:Name="mapImage" South="53.54031" North="53.74871" West="8.08594" East="8.43750"
Source="10_535_330.jpg" Opacity=".5"/>
<map:MapGraticule Opacity="0.6"/>
<map:MapScale Margin="4" Opacity="0.8"/>
@ -196,17 +198,28 @@
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Name="mouseLocation" Margin="4" VerticalAlignment="Center"/>
<TextBlock Name="mouseLocation" Margin="5" VerticalAlignment="Bottom" FontFamily="Consolas"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Slider ToolTip="Zoom Level" Margin="4" Width="100" SmallChange="0.01"
Minimum="{Binding MinZoomLevel, ElementName=map}"
Maximum="{Binding MaxZoomLevel, ElementName=map}"
Value="{Binding TargetZoomLevel, ElementName=map}"/>
<Slider ToolTip="Heading" Margin="4" Width="100" Minimum="0" Maximum="360" SmallChange="5" LargeChange="45"
Value="{Binding TargetHeading, ElementName=map}"/>
<CheckBox ToolTip="Map Overlay" Margin="4" VerticalAlignment="Center" Content="Seamarks" Click="SeamarksClick"/>
<ComboBox ToolTip="Main Tile Layer" Margin="4" DisplayMemberPath="SourceName" SelectedIndex="0"
ItemsSource="{Binding Source={StaticResource TileLayersView}}"/>
<StackPanel Margin="5">
<TextBlock Text="Zoom Level" Margin="0,0,0,2" HorizontalAlignment="Center" Foreground="Gray" FontSize="10"/>
<Slider ToolTip="Zoom Level" Width="100" VerticalAlignment="Center" SmallChange="0.01"
Minimum="{Binding MinZoomLevel, ElementName=map}"
Maximum="{Binding MaxZoomLevel, ElementName=map}"
Value="{Binding TargetZoomLevel, ElementName=map}"/>
</StackPanel>
<StackPanel Margin="5">
<TextBlock Text="Heading" Margin="0,0,0,2" HorizontalAlignment="Center" Foreground="Gray" FontSize="10"/>
<Slider ToolTip="Heading" Width="100" VerticalAlignment="Center" SmallChange="5" LargeChange="45"
Minimum="0" Maximum="360" Value="{Binding TargetHeading, ElementName=map}"/>
</StackPanel>
<StackPanel Margin="5">
<TextBlock Text="Image Opacity" Margin="0,0,0,2" HorizontalAlignment="Center" Foreground="Gray" FontSize="10"/>
<Slider ToolTip="Image Opacity" Width="100" VerticalAlignment="Center"
Minimum="0" Maximum="1" Value="{Binding Opacity, ElementName=mapImage}"/>
</StackPanel>
<CheckBox ToolTip="Seamarks Overlay" Margin="7" VerticalAlignment="Bottom" Content="Seamarks" Click="SeamarksClick"/>
<ComboBox ToolTip="Tile Layer" Margin="5" VerticalAlignment="Bottom" DisplayMemberPath="SourceName"
SelectedIndex="0" ItemsSource="{Binding Source={StaticResource TileLayersView}}"/>
</StackPanel>
</Grid>
</Grid>

View file

@ -2,6 +2,7 @@
using MapControl;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
@ -33,7 +34,7 @@ namespace WpfApplication
InitializeComponent();
ICollection<object> polylines = (ICollection<object>)Resources["Polylines"];
var polylines = (ICollection<object>)Resources["Polylines"];
polylines.Add(
new SamplePolyline
{
@ -45,7 +46,7 @@ namespace WpfApplication
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")
});
ICollection<object> points = (ICollection<object>)Resources["Points"];
var points = (ICollection<object>)Resources["Points"];
points.Add(
new SamplePoint
{
@ -84,7 +85,7 @@ namespace WpfApplication
});
points.Add(movingPoint);
ICollection<object> pushpins = (ICollection<object>)Resources["Pushpins"];
var pushpins = (ICollection<object>)Resources["Pushpins"];
pushpins.Add(
new SamplePoint
{
@ -110,8 +111,7 @@ namespace WpfApplication
Location = new Location(53.5207, 8.2323)
});
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(0.1);
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.1) };
timer.Tick += MovePoint;
timer.Start();
}
@ -151,7 +151,15 @@ namespace WpfApplication
private void MapMouseMove(object sender, MouseEventArgs e)
{
mouseLocation.Text = map.ViewportPointToLocation(e.GetPosition(map)).ToString();
var location = map.ViewportPointToLocation(e.GetPosition(map));
var longitude = Location.NormalizeLongitude(location.Longitude);
var latString = location.Latitude < 0 ?
string.Format(CultureInfo.InvariantCulture, "S {0:00.00000}", -location.Latitude) :
string.Format(CultureInfo.InvariantCulture, "N {0:00.00000}", location.Latitude);
var lonString = longitude < 0 ?
string.Format(CultureInfo.InvariantCulture, "W {0:000.00000}", -longitude) :
string.Format(CultureInfo.InvariantCulture, "E {0:000.00000}", longitude);
mouseLocation.Text = latString + "\n" + lonString;
}
private void MapManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)

View file

@ -10,7 +10,7 @@ using System.Windows;
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.10")]
[assembly: AssemblyFileVersion("1.1.10")]
[assembly: AssemblyVersion("1.2.0")]
[assembly: AssemblyFileVersion("1.2.0")]
[assembly: ComVisible(false)]
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

View file

@ -96,6 +96,9 @@
<Name>MapControl.WPF</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="10_535_330.jpg" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.