This project has moved. For the latest updates, please go here.

Drawing Tools

Mar 18, 2013 at 12:32 PM
I would like to draw at run-time a line or polygon onto the map.

Is the xaml map suited for these operations?
It works excellent for displaying data, but has someone tried changing these lines at run-time?

I guess my question is: Where should i start to implement these features?
Mar 18, 2013 at 5:40 PM
Nevermind, i found the solution :)

What i did was:

I moved the translating of the map to happen on a middle mouse click, leaving the left click open for interpretation.

And then i Reactive Extension to listen to the mouse click, drag and release, allowing me two have 2 positions with lat and long. I calculate a circle based on these points, and add them to the Observable collection allowing me to draw a circle on the map.
            var leftMouseDown = Observable.FromEventPattern<MouseButtonEventArgs>(map, "MouseLeftButtonDown");
            var leftMouseUp = Observable.FromEventPattern<MouseButtonEventArgs>(map, "MouseLeftButtonUp");

            var drag = leftMouseDown
    .Select(args =>  map.ViewportPointToLocation(args.EventArgs.GetPosition(map)))
    .TakeUntil(leftMouseUp)
    .CombineLatest(leftMouseUp
        .Select(args =>  map.ViewportPointToLocation(args.EventArgs.GetPosition(map)))
        .Take(1), (p1, p2) => new { p1, p2 })
    .Repeat();

            drag.Subscribe(a =>
                {

                    Points.Add(new Circle(a.p1.Latitude, a.p1.Longitude, a.p2.Latitude, a.p2.Longitude));
                });

        }
Coordinator
Mar 18, 2013 at 5:51 PM
You could always manipulate the Locations collection of a MapPolyline at runtime.

In one application that uses the MapControl we have a SurfaceInkCanvas on top of the map to enable freehand drawing. When drawing is finished, we disable the InkCanvas (so that the MapControl receives mouse and touch input) and create MapPolylines from the drawing strokes by transforming the stroke points into Locations.
Mar 19, 2013 at 1:39 PM
If i were to create a circle, that changes size as the map zooms, is it best to create a map-polyline?

I see it is the only control that calls updategeometry, or am i missing something.
Coordinator
Mar 19, 2013 at 6:07 PM
Edited Mar 19, 2013 at 6:07 PM
No, you could simply create a Path with an appropriate Geometry, i.e. an EllipseGeometry, and apply the Map's ScaleTransform to that Geometry.
<map:Map Name="map" Center="53.5,8.2" ZoomLevel="12">
    <Path map:MapPanel.Location="53.5,8.2" Stroke="Blue" StrokeThickness="3">
        <Path.Data>
            <EllipseGeometry RadiusX="1000" RadiusY="1000"
                Transform="{Binding ScaleTransform, ElementName=map}"/>
        </Path.Data>
    </Path>
</map:Map>
ScaleTransform transforms from meters to pixels, hence the circle radius is given in meters.
Feb 6, 2015 at 3:42 PM
Hi Clemens,

I can't get the ellipse to work when generating the path within a MapItemsControl. It is not placed in the correct location (not centered on the coordinates). It seems the DesiredSize is not available in the MapPanel.ArrangeElementWithLocation method. Do you have any ideas on how I could fix this?

regards, Tilli
Coordinator
Feb 6, 2015 at 4:15 PM
Take a look at the PointItemStyle in the sample application. It draws circles that are centered at the MapItem location.
Feb 6, 2015 at 5:20 PM
yes, I saw it. I see no clue there, though, what exactly makes the Ellipse position exactly in the center of the bound location. The canvas is not cubical (grid with label beside it).

also I have a base-class of multiple concrete types (regions, points) being bound to and therefore I cannot directly override the Template property of the MapItem, but use DataTemplates. Therefore there is an additional ContentPresenter which hosts the DataTemplate of my model.