It has been long anticipated and finally it arrived as a Community Technology Preview (CTP): The Virtual Earth Silverlight MapControl. To get access to the CTP you need to register at Microsoft Connect. Once you are registered you will have access to an installer which gets you the libraries as well as the offline documentation. There is also an Interactive SDK, a link to a getting stated guide on Via Windows Live and another one that allows you to submit bugs and feature requests.
One of the things that I like particularly about Silverlight is the ability to separate the work of a designer from the developers work. Most developers are quite happy with a button that executes the desired function when you click on it but designers pay much more attention on the details of the presentation. They might look for a button with rounded corners or images in the background and a nice animation when you mouse over it. With Silverlight the developer can put his button on the page and start working in Visual Studio on the code while at the same time the designer can use Expression Blend to work on the style.
But aside from that there are a lot of immediate advantages for Virtual Earth:
- The map rendering is much smoother between zoom-levels since it leverages the DeepZoom technology.
- The graphics framework is much more powerful not only in terms of animations and integration of videos but also in terms of rendering large numbers of points of interest or more complex polygons.
- And finally we can write our code end-to-end in .NET. Remember that with the AJAX control we created an AJAX call to a .NET web service or web handler which then queried the database and returned JSON-objects for our points of interest.
Well the procedure is pretty much the same with Silverlight but it is now all in .NET and doesn’t even require half of the lines of code that we needed in AJAX.
Lets have a look at the last point and create a quick application with the Virtual Earth Silverlight MapControl that connects to a database to retrieve the points of interest in the current map view.
Integrating the Virtual Earth Silverlight MapControl
Before we get started we need to verify that we have the Visual Studio 2008 SP1 and the Silverlight Tools for Visual Studio 2008 SP1 installed. We also need to register at Microsoft Connect and install the Virtual Earth Silverlight MapControl CTP. Once we have prepared our development environment we can start Visual Studio and create a new Silverlight project…
…with an ASP.NET Web project.
To the Silverlight project (not the Web project) we add now a reference to the Microsoft.VirtualEarth.MapControl.dll. By default this is installed in C:Program FilesMicrosoft Virtual Earth Silverlight Map ControlCTPLibraries.
In the Page.xaml we add a reference to our assembly and embed our map. For the map we can already define a number of properties such as the centre point (Center), the zoom-level (ZoomLevel) and the style (Mode). We also define a MapLayer which will host our points of interest as a child of the map. Finally we add a button that will allow us to switch the POI layer on and off.
<UserControl x:Class="VE_SL_DBConn.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl"> <Grid x:Name="LayoutRoot" Background="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <m:Map Name="MyMap" Center="51.461962075378054, -0.9260702133178665" ZoomLevel="17" Mode="Road"> <m:Map.Children> <m:MapLayer x:Name="MyPOI"></m:MapLayer> </m:Map.Children> </m:Map> <Button Height="25" Width="100" HorizontalAlignment="Right" VerticalAlignment="Top" Click="LoadPoiInMapView_Click"> <TextBlock x:Name="btnPOI">Get POI</TextBlock> </Button> </Grid> </UserControl>
You can already compile the project and have a look at your map but obviously we are not yet connected to our database.
Querying the Database
Now that we have defined our map we prepare the database connection. A quick and simple way to do so is the OR-mapping in the LINQ to SQL classes. In the web project add a new LINQ to SQL mapper.
Now simply drag and drop a table from your Server Explorer to the design surface of the dbml file…
…and in the properties of the newly created data context set the Serialization Mode to unidirectional.
Next we create a web service. We add a Silverlight-enabled WCF Service to our web project.
Since we have already mapped the table in our SQL Server to objects we only need a minimum of code. As input parameters we take the bounding box of the current map view in order to reduce the number of returned results. We will determine the bounding box a little bit later. The result is returned as a List of objects.
Imports System.ServiceModel Imports System.ServiceModel.Activation <ServiceContract(Namespace:="DataService")> _ <AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)> _ Public Class DataService <OperationContract()> _ Public Function GetPOIinView(ByVal NWlat As Double, _ ByVal NWlon As Double, _ ByVal SElat As Double, _ ByVal SELon As Double) _ As List(Of UK_low_bridges_all) Dim datacontext As New HannesPOIDataContext Return ((From UK_low_bridges_alls _ In datacontext.UK_low_bridges_alls _ Where UK_low_bridges_alls.Latitude <= NWlat And _ UK_low_bridges_alls.Latitude >= SElat And _ UK_low_bridges_alls.Longitude >= NWlon And _ UK_low_bridges_alls.Longitude <= SELon).ToList()) End Function End Class
To use this web service in our Silverlight project (not the Web project) we add a Service Reference:
Connecting the Map to the Web Service
In order to connect the map to the web service we add some code to our code-file for our page (Page.xaml.vb). First we import the namespaces for our Virtual Earth Silverlight MapControl and our web service. Next we create a procedure that is to be executed when we click on our button (LoadPoiInMapView_Click). To load the POI we add an event handler that fires when the map view changed, i.e. when we finished zooming or panning. This event handler will determine the bounding box of the map and use it as parameters for an asynchronous call to our web service. Once the call returns the result we will render the POI in our map layer.
Imports VE_SL_DBConn.DataServiceReference Imports Microsoft.VirtualEarth.MapControl Partial Public Class Page Inherits UserControl Public Sub New() InitializeComponent() End Sub Public Sub LoadPoiInMapView_Click(ByVal sender As Object, _ ByVal e As RoutedEventArgs) If btnPOI.Text = "Get POI" Then AddHandler MyMap.ViewChangeEnd, AddressOf MyMap_ViewChanged btnPOI.Text = "Remove POI" Dim bounds As LocationRect = MyMap.GetBoundingRectangle() Dim svc As New DataServiceClient() AddHandler svc.GetPOIinViewCompleted, AddressOf svc_GetPoiInMapViewCompleted svc.GetPOIinViewAsync(bounds.Northwest.Latitude, _ bounds.Northwest.Longitude, _ bounds.Southeast.Latitude, _ bounds.Southeast.Longitude) Else RemoveHandler MyMap.ViewChangeEnd, AddressOf MyMap_ViewChanged MyPOI.Children.Clear() btnPOI.Text = "Get POI" End If End Sub Private Sub MyMap_ViewChanged(ByVal sender As Object, _ ByVal e As MapEventArgs) MyPOI.Children.Clear() Dim bounds As LocationRect = MyMap.GetBoundingRectangle() Dim svc As New DataServiceClient() AddHandler svc.GetPOIinViewCompleted, AddressOf svc_GetPoiInMapViewCompleted svc.GetPOIinViewAsync(bounds.Northwest.Latitude, _ bounds.Northwest.Longitude, _ bounds.Southeast.Latitude, _ bounds.Southeast.Longitude) End Sub Private Sub svc_GetPoiInMapViewCompleted(ByVal sender As Object, _ ByVal e As GetPOIinViewCompletedEventArgs) If e.Error Is Nothing Then For i = 0 To e.Result.Count - 1 Dim point As New Ellipse() point.Width = 10 point.Height = 10 point.Fill = New SolidColorBrush(Colors.Red) point.Opacity = 0.65 Dim location As New Location(e.Result(i).Latitude, e.Result(i).Longitude) MapLayer.SetMapPosition(point, location) ToolTipService.SetToolTip(point, e.Result(i).Name) MyPOI.Children.Add(point) Next Else MessageBox.Show("Error occurred while loading POI from database", _ "Error", MessageBoxButton.OK) End If End Sub End Class
That’s it, we’re done. You will find the sample code here.
In this quick sample we had a look at the database connection for the Virtual Earth Silverlight MapControl. Aside from the fact that we did the coding end-to-end in .NET we could also have a look at the performance and compare the user experience in various browsers.
Yes, using Silverlight may not have the reach of HTML (yet) since you need to install a browser plug-in and most of all since it isn’t supported on all possible platforms and browsers (yet). It isn’t as powerful as the Windows Presentation Framework (WPF) either but it is a great compromise between outreach and richness.