Map your Data – Part 11

In my last post, I mentioned that I'd be building a demo of how to add SQL 2008 spatial data to a WPF layer over VE.  I've made some good progress on that front, and will post the demo soon (hopefully by this week's end.)

Building off the great work Adam Eversole, Jared Bienz, and Marc Schweigert, I set off to build a VE control that wasn't just WPF enabled, but rather, I wanted it to be WPF friendly.  In other words, I wanted the experience of adding a WPF mapping layer over VE to feel natural to the WPF developer.  After some discussion with Jared, I think I'm heading down the right path now.

In an earlier post in this series, I mentioned that I was able to adapt Marc's demo to plot points over VE using a block of code to do client-side latitude+longitude to x+y coordinate transformations.  Unfortunately, my implementation left something to be desired.  I was reaching into Marc's control at a level deeper than was optimal, and as a result, my code was pretty contorted.

Once I thought a little more deeply about what it was that I was trying to do, I realized that I was simply trying to add a set of layers over the Virtual Earth map using WPF as the layering engine.  In kicking this concept around with Jared, we examined a couple good cases in point, most notably Beatriz Costa's Planet ListBox sample.

Marc demonsrated how to place a Topmost WPF Window over a web page hosting VE within a .NET 3.5 SP1 WebBrowser control.  I added the plumbing to add an arbitrary set of child Canvases to this topmost Window and then to add geographic entities to them.  I also did some work to make sure that the control and its properties were presented naturally to the WPF developer/designer.  The XAML for this looks something like this:

<Window x:Class="WpfVeTest.Window1"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ve="clr-namespace:WpfVeCtrlLib;assembly=WpfVeCtrlLib"
Title="Window1" Height="768" Width="1024">
<Canvas>
<ve:WpfVeMap x:Name="WpfVeMap" Canvas.Left="224" Canvas.Top="84" ZoomLevel="7">
<ve:WpfVeMap.MapLayers>
<ve:WpfVeMapLayer LayerName="Bricks" ItemsSource="{Binding Bricks}" WellKnownTextPath="WellKnownText"/>
<ve:WpfVeMapLayer LayerName="Territories" ItemsSource="{Binding Territories}" WellKnownTextPath="WellKnownText"/>
<ve:WpfVeMapLayer LayerName="Districts" ItemsSource="{Binding Districts}" WellKnownTextPath="WellKnownText"/>
</ve:WpfVeMap.MapLayers>
</ve:WpfVeMap>
</Canvas>
</Window>

The map control just has a set of layers, each of which are bound to a set of items which has a property containing the well-known text (WKT) describing the geographic entities therein.  Zoom level, center point, and other properties are set at the control level, but each layer completely contains its own set of geographic entities.

The WKT is parsed into intermediate “spatial objects”, which correspond to sets of WPF System.Windows.Shapes.  If a WellKnownTextPath is provided, I reflect on the layer’s items to get to the property and do the parsing work.  Then, I call the client side transformation routine to translate the latitude+longitude pairs into x+y coordinates.

My parsing yields System.Windows.Shapes.Path, Polyline, or Ellipse objects corresponding to WKT POLYGON, MULTILINE, or POINT objects respectively.  I’m using the Path rather than the Polygon because WKT POLYGONs may include interior holes, but the WPF Polygon does not.  I will dig deeper into this parsing logic in a future post.

While all this is nice, the true power of WPF isn’t evident until you’re able to apply custom styling to the objects you’ve placed on the control.  Following the ListBox’s guidance, I enabled each layer to register a custom StyleSelector for its Paths, Polylines, and Ellipses.  The full power of WPF is now at your disposal, as you can make data driven decisions about which style to apply, add triggers to the style, or whatever.

Getting the WPFisms right was a bit of an adventure, so I’ll post about this process as well on the off chance that it might benefit others trying to design controls.

More soon…