The fundamental barrier to using WPF or Silverlight to plot data on a map is knowing where to plot geocoded points on a rectangle.  A geocoded point is simply a latitude+longitude pair (I'll show you how to obtain these later), but translating these to an arbitrary rectangule is non-trivial, especially if that rectangle covers a wide region of the earth's surface.

Thankfully, the MapPoint Web Service SDK provides a great boilerplate function for this which translates geocoded points to a pixel coordinate (x+y pair) with a high degree of accuracy at both large and small scales.  This is the done via a method on MapPoint's PointConverter, and I'll post it with a demo on my personal blog (so I don't clutter up things here or divert this blog from its intended purpose.)

To use the PointConverter, you'll need to have a geocoded point (latitude+longitude), the size of the rectangle on which you plan to plot the point (pixel width + pixel height), the geographic scale of map region you plan to show in the rectangle (kilometers), and the center point of the map region (latitude+longitude.)  Given all that, the PointConverter's LatLongToPixel method will provide you wiht the pixel coordinate (x+y) that corresponds to the geocoded point (latitude+longitude) that you pointed in using code that looks something like this:

foreach (Thing thing in model.Things)

{

  if ((!double.IsNaN(thing.Latitude)) && (!double.IsNaN(thing.Longitude)))

  {

    LatLong latLong = new LatLong { Latitude  = thing.Latitude,

                                    Longitude = thing.Longitude };

    PixelCoord point = PointConverter.LatLongToPoint(

              latLong,

              new System.Drawing.Size(Convert.ToInt32(canvas.Width),

                                      Convert.ToInt32(canvas.Height)),

              viewscale,

              centerPoint);

    Button button =  new Button { Style = GetButtonStyle(thing) };

                   

    canvas.Children.Add(button);

    Canvas.SetLeft(button, point.X - (button.Width / 2));

    Canvas.SetTop(button,  point.Y - (button.Height / 2));

}

public static PixelCoord LatLongToPoint(

                                    LatLong latLong,

                                    Size imageSizeInPixels,

                                    double viewGroundDistanceInKilometers,

                                    LatLong viewCenterpoint)

{

    /* lots of non-trivial math from MapPoint Web Service SDK */

}

 

This code of course presumes the presence of a Canvas, a method that returns a Style that can be applied to a Button, and a known viewscale and centerPoint value for a map region.  I'll post a link over to my personal blog which contains a working sample of this at the start of my next posting in this series.

The point I'd like to make here though is that this method provides you with complete freedom of design for what you place at those points on the map.  You'll recall that a WPF Button is completely "lookless", and that a Style can completely replace its appearance with anything you can dream up.  This will allow you to place thematic, animated, and even 3D markers on the map that can respond to user requests to filter or requery data without having to call the server to rerender, yielding a performance and even a monetary cost savings.

More on this next time...