Last week we launched a new wave of Bing Maps. My esteemed colleague Chris Pendleton has blogged about some of the changes here, here, here and here. One of the main announcements has been the launch of the Bing Maps Silverlight Control v1. You will find the interactive SDK here, the full reference on MSDN here and the download here. This control has been available as a Community Technology Preview (CTP) for quite a while but those of you who have been waiting for a fully supported version before getting involved may not be too familiar with it yet. If you did work with the CTP please be aware that it is time-bombed and will stop working by the end of the year; so please consider updating your application soon.
If you have been working with the Bing Maps AJAX Control before you may actually be missing a few things that came in handy if you wanted to display additional information like for a example a Photosynth collection. This was quite simple in the AJAX control since you could simply generate an iFrame in Photosynth and just add it to a VEShape-object using the VEShape.SetDescription-method. You can look at a sample here and download the source here).
Since pushpins in the Silverlight control don’t have an info-box like the ones in the AJAX-control the approach here is quite different but it still works very well. The major obstacle appear to be that we cannot directly integrate HTML-code into our Silverlight application. The solution is actually to use the HTML Bridge in order to lay a HTML DIV-element on top of the Silverlight control and arrange it appropriately. Of course you can write everything from the scratch but the guys from divelements have created a Silverlight-Control HtmlHost for us that you can download for free and use to add and control HTML content directly from your Silverlight application. Let’s have a crack at it. For this walkthrough we will need
First we create a new Silverlight application and add references to our Bing Maps Silverlight Control
In the MainPage.xaml we add a reference to our Bing Maps Silverlight control…
…and the the map itself with a pushpin at the location where we our Photosynth collection is. We also attach an event to the pushpin that fires when we click on it.
<m:Map CredentialsProvider="YOUR BING MAPS KEY" Mode="AerialWithLabels" Center="32.362980181127874,-64.71483707427978" ZoomLevel="17"> <m:Pushpin Name="pinMartelloTower" Location="32.362980181127874,-64.71483707427978" MouseLeftButtonDown="pinMartelloTower_MouseLeftButtonDown"/> </m:Map>
If you had done something like this with the CTP before you will notice a few differences:
- The namespace for the Bing Maps Silverlight Control has changed
- We now need to provide a CredentialsProvider in order to authenticate. This is basically the Bing Maps Key that we generated before.
- We have now a Pushpin-object that we can use as a child of a map
In my sample here I chose to bring up the Photosynth collection as part of a ChildWindow. A ChildWindow is a Silverlight control that comes with the Silverlight Toolkit. So let’s add a ChildWindow as new object to our Silverlight-project. I call it Photosynth. The trouble with a ChildWindow and HTML-DIV-elements on top is that the ChildWindow has an animation and explodes when you open it. If you would just add the HTML-DIV-element when the ChildWindow opens it would appear in the bottom-right quadrant of the screen. In order to avoid this we can simply remove the animation by changing the template in Expression Blend. In Visual Studio just right-click on the ChildWindow and select “Open in Expression Blend” from the context menu.
In Expression Blend right-click on the ChildWindow-object and select “Edit Template” => “Edit a Copy”.
Now we switch to code-view and remove the whole VisualStateManager that handles the StoryBoards for opening and closing the window. By default this would start around line 119:
While we’re at it we can optionally make a few more changes to adjust the design:
Now we can leave Expression Blend and go back to Visual Studio. In order to add the HtmlHost from divelements right-click on the Toolbox, select “Choose Items” from the context menu and add the Divelements.SilverlightTools.dll from the location where you extracted the download.
Now drag&drop the control on your ChildWindow. This will automatically add the required namespace you only need to add a Name-property to the HtmlHost. Your XAML-should now look like this
<controls:ChildWindow x:Class="SilverlightApplication2.Photosynth" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" xmlns:my="clr-namespace:Divelements.SilverlightTools;assembly=Divelements.SilverlightTools" Width="400" Height="300" Title="Photosynth"> <controls:ChildWindow.Resources> … </controls:ChildWindow.Resources> <controls:ChildWindow.Style> <StaticResource ResourceKey="ChildWindowStyle"/> controls:ChildWindow.Style> <Grid x:Name="LayoutRoot" Margin="2"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <my:HtmlHost Name="htmlHost"></my:HtmlHost> </Grid> </controls:ChildWindow>
Finally we can start coding. The only code we need is actually in the MainPage.xaml.vb. When we initialize the page we also add a handler which resizes the ChildWindow whenever the size of the browser window changes.
When we click on the pushpin we set the title for the ChildWindow as well as the source for the HtmlHost. In this case we just add the iFrame which we can copy directly from Photosynth…
…and make to minor changes:
- we change the width and height of the iFrame to 100%
- we set the URL-parameter delayLoad from true to false. By default the Photosynth viewer would show a static image and only load the collection after you clicked on this image. By changing this parameter we load the collection immediately.
Imports System.Windows.Browser Partial Public Class MainPage Inherits UserControl Public myHeight As Integer Public myWidth As Integer Private WithEvents cwPhotosynth As New Photosynth Public Sub New() InitializeComponent() AddHandler LayoutRoot.SizeChanged, AddressOf Page_SizeChanged End Sub Private Sub Page_SizeChanged(ByVal sender As Object, ByVal e As SizeChangedEventArgs) myWidth = CInt(e.NewSize.Width) myHeight = CInt(e.NewSize.Height) cwPhotosynth.Width = e.NewSize.Width * 0.8 cwPhotosynth.Height = e.NewSize.Height * 0.8 End Sub Private Sub pinMartelloTower_MouseLeftButtonDown _ (ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) cwPhotosynth.Title = "Martello Tower" cwPhotosynth.htmlHost.SourceHtml = _ "<iframe frameborder='0' src='http://photosynth.net/embed.aspx?cid=ba12ab48-6899-4d7f-b28c-624f5f7ff4f0” + _ &delayLoad=false&slideShowPlaying=false' width='100%' height='100%'>" cwPhotosynth.Show() End Sub End Class
Well that’s already it:
Note: if you download the sample code you need to create a Bing Maps Key and enter it into the XAML in order to load the Bing Maps. Also note that the solution was build with Visual Studio 2010 Beta 2, however all methods work as well in Visual Studio 2008 SP1