mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
240 lines
9.2 KiB
C#
240 lines
9.2 KiB
C#
// WPF MapControl - http://wpfmapcontrol.codeplex.com/
|
|
// Copyright © 2012 Clemens Fischer
|
|
// Licensed under the Microsoft Public License (Ms-PL)
|
|
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Data;
|
|
using System.Windows.Media;
|
|
using System.Windows.Shapes;
|
|
|
|
namespace MapControl
|
|
{
|
|
/// <summary>
|
|
/// An open map polygon, defined by a collection of geographic locations in the Locations property.
|
|
/// </summary>
|
|
public class MapPolyline : FrameworkElement
|
|
{
|
|
public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.Brush = (Brush)e.NewValue));
|
|
|
|
public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(
|
|
typeof(MapPolyline));
|
|
|
|
public static readonly DependencyProperty StrokeDashArrayProperty = Shape.StrokeDashArrayProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.DashStyle = new DashStyle((DoubleCollection)e.NewValue, ((MapPolyline)o).StrokeDashOffset)));
|
|
|
|
public static readonly DependencyProperty StrokeDashOffsetProperty = Shape.StrokeDashOffsetProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.DashStyle = new DashStyle(((MapPolyline)o).StrokeDashArray, (double)e.NewValue)));
|
|
|
|
public static readonly DependencyProperty StrokeDashCapProperty = Shape.StrokeDashCapProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.DashCap = (PenLineCap)e.NewValue));
|
|
|
|
public static readonly DependencyProperty StrokeStartLineCapProperty = Shape.StrokeStartLineCapProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.StartLineCap = (PenLineCap)e.NewValue));
|
|
|
|
public static readonly DependencyProperty StrokeEndLineCapProperty = Shape.StrokeEndLineCapProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.EndLineCap = (PenLineCap)e.NewValue));
|
|
|
|
public static readonly DependencyProperty StrokeLineJoinProperty = Shape.StrokeLineJoinProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.LineJoin = (PenLineJoin)e.NewValue));
|
|
|
|
public static readonly DependencyProperty StrokeMiterLimitProperty = Shape.StrokeMiterLimitProperty.AddOwner(
|
|
typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).Drawing.Pen.MiterLimit = (double)e.NewValue));
|
|
|
|
public static readonly DependencyProperty TransformStrokeProperty = DependencyProperty.Register(
|
|
"TransformStroke", typeof(bool), typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).SetPenThicknessBinding()));
|
|
|
|
public static readonly DependencyProperty LocationsProperty = DependencyProperty.Register(
|
|
"Locations", typeof(LocationCollection), typeof(MapPolyline), new FrameworkPropertyMetadata((o, e) => ((MapPolyline)o).UpdateGeometry()));
|
|
|
|
protected readonly GeometryDrawing Drawing = new GeometryDrawing();
|
|
|
|
static MapPolyline()
|
|
{
|
|
MapPanel.ParentMapPropertyKey.OverrideMetadata(
|
|
typeof(MapPolyline),
|
|
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, ParentMapPropertyChanged));
|
|
}
|
|
|
|
public MapPolyline()
|
|
{
|
|
Drawing.Pen = new Pen
|
|
{
|
|
Brush = Stroke,
|
|
Thickness = StrokeThickness,
|
|
DashStyle = new DashStyle(StrokeDashArray, StrokeDashOffset),
|
|
DashCap = StrokeDashCap,
|
|
StartLineCap = StrokeStartLineCap,
|
|
EndLineCap = StrokeEndLineCap,
|
|
LineJoin = StrokeLineJoin,
|
|
MiterLimit = StrokeMiterLimit
|
|
};
|
|
}
|
|
|
|
public MapBase ParentMap
|
|
{
|
|
get { return MapPanel.GetParentMap(this); }
|
|
}
|
|
|
|
public Brush Stroke
|
|
{
|
|
get { return (Brush)GetValue(StrokeProperty); }
|
|
set { SetValue(StrokeProperty, value); }
|
|
}
|
|
|
|
public double StrokeThickness
|
|
{
|
|
get { return (double)GetValue(StrokeThicknessProperty); }
|
|
set { SetValue(StrokeThicknessProperty, value); }
|
|
}
|
|
|
|
public DoubleCollection StrokeDashArray
|
|
{
|
|
get { return (DoubleCollection)GetValue(StrokeDashArrayProperty); }
|
|
set { SetValue(StrokeDashArrayProperty, value); }
|
|
}
|
|
|
|
public double StrokeDashOffset
|
|
{
|
|
get { return (double)GetValue(StrokeDashOffsetProperty); }
|
|
set { SetValue(StrokeDashOffsetProperty, value); }
|
|
}
|
|
|
|
public PenLineCap StrokeDashCap
|
|
{
|
|
get { return (PenLineCap)GetValue(StrokeDashCapProperty); }
|
|
set { SetValue(StrokeDashCapProperty, value); }
|
|
}
|
|
|
|
public PenLineCap StrokeStartLineCap
|
|
{
|
|
get { return (PenLineCap)GetValue(StrokeStartLineCapProperty); }
|
|
set { SetValue(StrokeStartLineCapProperty, value); }
|
|
}
|
|
|
|
public PenLineCap StrokeEndLineCap
|
|
{
|
|
get { return (PenLineCap)GetValue(StrokeEndLineCapProperty); }
|
|
set { SetValue(StrokeEndLineCapProperty, value); }
|
|
}
|
|
|
|
public PenLineJoin StrokeLineJoin
|
|
{
|
|
get { return (PenLineJoin)GetValue(StrokeLineJoinProperty); }
|
|
set { SetValue(StrokeLineJoinProperty, value); }
|
|
}
|
|
|
|
public double StrokeMiterLimit
|
|
{
|
|
get { return (double)GetValue(StrokeMiterLimitProperty); }
|
|
set { SetValue(StrokeMiterLimitProperty, value); }
|
|
}
|
|
|
|
public bool TransformStroke
|
|
{
|
|
get { return (bool)GetValue(TransformStrokeProperty); }
|
|
set { SetValue(TransformStrokeProperty, value); }
|
|
}
|
|
|
|
public LocationCollection Locations
|
|
{
|
|
get { return (LocationCollection)GetValue(LocationsProperty); }
|
|
set { SetValue(LocationsProperty, value); }
|
|
}
|
|
|
|
public PathGeometry TransformedGeometry
|
|
{
|
|
get { return Drawing.Geometry as PathGeometry; }
|
|
}
|
|
|
|
public double TransformedStrokeThickness
|
|
{
|
|
get { return Drawing.Pen.Thickness; }
|
|
}
|
|
|
|
protected override void OnRender(DrawingContext drawingContext)
|
|
{
|
|
drawingContext.DrawDrawing(Drawing);
|
|
}
|
|
|
|
protected virtual void UpdateGeometry()
|
|
{
|
|
UpdateGeometry(false);
|
|
}
|
|
|
|
protected void UpdateGeometry(bool closed)
|
|
{
|
|
if (ParentMap != null && Locations != null && Locations.Count > 0)
|
|
{
|
|
Drawing.Geometry = CreateGeometry(Locations, closed);
|
|
}
|
|
else
|
|
{
|
|
Drawing.Geometry = null;
|
|
}
|
|
}
|
|
|
|
private Geometry CreateGeometry(LocationCollection locations, bool closed)
|
|
{
|
|
StreamGeometry geometry = new StreamGeometry
|
|
{
|
|
Transform = ParentMap.ViewportTransform
|
|
};
|
|
|
|
using (StreamGeometryContext sgc = geometry.Open())
|
|
{
|
|
sgc.BeginFigure(ParentMap.MapTransform.Transform(locations.First()), closed, closed);
|
|
|
|
if (Locations.Count > 1)
|
|
{
|
|
sgc.PolyLineTo(ParentMap.MapTransform.Transform(locations.Skip(1)), true, true);
|
|
}
|
|
}
|
|
|
|
return geometry;
|
|
}
|
|
|
|
private void SetPenThicknessBinding()
|
|
{
|
|
BindingBase binding = new Binding { Source = this, Path = new PropertyPath(MapPolyline.StrokeThicknessProperty)};
|
|
|
|
if (TransformStroke && ParentMap != null)
|
|
{
|
|
MultiBinding multiBinding = new MultiBinding { Converter = new PenThicknessConverter() };
|
|
multiBinding.Bindings.Add(binding);
|
|
multiBinding.Bindings.Add(new Binding { Source = ParentMap, Path = new PropertyPath(MapBase.CenterScaleProperty)});
|
|
binding = multiBinding;
|
|
}
|
|
|
|
BindingOperations.SetBinding(Drawing.Pen, Pen.ThicknessProperty, binding);
|
|
}
|
|
|
|
private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
MapPolyline polyline = obj as MapPolyline;
|
|
|
|
if (polyline != null)
|
|
{
|
|
polyline.UpdateGeometry();
|
|
polyline.SetPenThicknessBinding();
|
|
}
|
|
}
|
|
|
|
private class PenThicknessConverter : IMultiValueConverter
|
|
{
|
|
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
return (double)values[0] * (double)values[1] * MapBase.MeterPerDegree;
|
|
}
|
|
|
|
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|
|
}
|