Home  >  

Silverlight 2.0 Mashup with Flickr and Virtual Earth

Author photo
AddThis Social Bookmark Button
Microsoft released Silverlight 2.0 beta 1 at MIX08 last week. Comparing to Silverlight 1.1, the 2.0 beta 1 release has significant improvements and changes. To evaluate the state of Silverlight 2.0 as a RIA development tool, I wrote a mashup application.

What this Silverlight application does is simple. It allows you search Flickr by entering a tag. The result (GeoRSS feed) will be displayed in a thumbnail image slider. You can click a thumbnail image, then the location will be displayed on a map (Microsoft Virtual Earth) as push pin and a larger image can be shown in the infobox when mouse-over the push pin. There are several controls on the application to control the map, such as toggle map control panel and zoom in/out with Silverlight slider. Here is the screen shot.

sil1.jpg


You can try this application here. Now let me show you the details on how this application was developed.

Development Tool

First, let's go over what we need for developing this mashup:

  • Silverlight 2.0 Beta 1 - This is the Silverlight plugin or runtime for the browsers. Very small foot print so the installation is quick.

  • Microsoft Visual Studio 2008

  • Silverlight 2.0 Tool Beta 1 for Visual Studio 2008 - For developers, VS 2008 fits better, even though Microsoft Expression Blend is another Silverlight application development tool. Blend is for designer as what Flash Studio is.

  • Silverlight 2.0 Beta SDK - This actually included in the above tool.

  • Microsoft Virtual Earth SDK 6.0 - What you really get is the help file for the VE 6.0 SDK. The VE SDK or API is in JavaScript so that you don't have anything actually installed to your computer.

  • IIS or other HTTP server (for a good reason explained later) - This is for testing your application locally.

An important reminder, if you have previous version of Silverlight tool for Visual Studio, you really need to uninstall it first. You would think Microsoft will take care of the upgrade, it doesn't at all.

Create a Silverlight 2.0 Project

Just like every other modern IDE driven development environment, you need create a project first with Visual Studio. The installation of Silverlight 2.0 Beta tool for VS 2008 gives you a Silverlight template. Once the project is created, the environment looks like this:

sil2.jpg


Here are a few things you would notice that are different from previous version:

  • There is a toolbar for Silverlight now at the left. It contains 30 Silverlight UI controls. This is the first time Silverlight provides build-in UI controls besides the TextBox control.

  • There is a visual design area at top with a slider for zoom in/out the view. But don't get too excited. The design area is read only. Other than view the UI, nothing can do there. To use the control toolbar, you drag and drop the control onto the source code. Yes, it is odd.

  • There is NO property inspection tool at right you'd expect, to help adjust UI control.

  • The generated files and the directory structure are different from previous version. One more XAML file, app.xaml (and code-behind file), is created. The test HTML file is created in ClientBin directory instead of in the project root.


Silverlight 1.1 is the past so I won't get into details to compare it. I'll just focus on developing a new Silverlight 2.0 application.

Develop the Application UI

There are two classes (XAML files) created to allow you work on:
  • App (app.xaml, app.xaml.cs) - This is the application class, which is required by every Silverlight-based application to start an application running and to show the main application UI. We don't work on this file unless need global data, resource, assets or functions.

  • Page (page.xaml, page.xaml.cs) - The UI design starts from here. It's the main UI of a Silverlight application. The Page class derives from UserControl and is implemented using a combination of one file for XAML markup (page.xaml) and one file for code-behind (page.xaml.cs).


By default, the page.xaml is created as this:

<UserControl x:Class="SilverlightVE20.Page"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
    </Grid>
</UserControl>
Now we can start dropping desired controls from the control toolbar onto the above code to form the intent UI. Speaking of default, if you are an Adobe Flex developer, you would just drag and drop the UI components on to the design area and the default look could be decent enough to allow you move on to code. That's not the case with Silverlight in VS. Try to drop a Button on the above code and see what will happen. The button will take over the whole space so that you can't find where button is, before you realize it needs to set the size to have a real button shown as a button.

Here is the final UI XAML:

<UserControl x:Class="SilverlightVE20.Page"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="1000" Height="540" Margin="10">
    <StackPanel Background="Black" HorizontalAlignment="Left" Orientation="Horizontal">
    <StackPanel Orientation="Vertical">

       <StackPanel Orientation="Horizontal" Margin="5" VerticalAlignment="Center"
                   Background="Azure">
         <TextBlock Text="Flickr Tag" VerticalAlignment="Center" Margin="5"/>
         <TextBox x:Name="feedURL" Text="" BorderBrush="Black" Margin="5" Width="150"/>
         <Button  x:Name="btnGetFeed" Content="Get it" Background="Aqua" Width="60"
                 Height="20" Click="btnGetFeed_Click"/>
         <Canvas Width="20"/>
         <CheckBox x:Name="showControl" Checked="showControl_Checked" 
                 Unchecked="showControl_Unchecked" Content="Show Map Control"/>
         <Canvas Width="20"/>
         <TextBlock Text="Map Zoom" VerticalAlignment="Center"/>
         <Slider x:Name="zoomMap" Minimum="1" Maximum="10" Value="4" LargeChange="1" 
                 ValueChanged="zoomMap_ValueChanged" 
                 MouseLeftButtonUp="zoomMap_MouseLeftButtonUp" Width="160"/>
         <TextBlock Text="5" VerticalAlignment="Center" x:Name="curZoom"/>
      </StackPanel>
            
            
      <StackPanel Orientation="Horizontal" Margin="5">
        </StackPanel>            
           <Border BorderThickness="1" BorderBrush="#D7D8ED" Margin="20" Width="700"
                   HorizontalAlignment="Left" Height="410" Background="White">
              <TextBlock x:Name="info" Width="350" Height="150" Text="info" 
                         TextWrapping="Wrap" Margin="20"/>
           </Border>
        </StackPanel>

        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" 
                    VerticalAlignment="Top" Width="150" Margin="5">
          <ListBox x:Name="imageList" Width="120" Height="500" 
            HorizontalAlignment="Center" SelectionChanged="imageList_SelectionChanged">
            <ListBox.ItemTemplate>
               <DataTemplate>
               <StackPanel Orientation="Vertical" Width="85" Height="85" 
                  HorizontalAlignment="Center">
                  <Image Source="{Binding thumbImage}" Width="75" Height="75" 
                               Margin="3" HorizontalAlignment="Center"/>
                </StackPanel>
                </DataTemplate>
             </ListBox.ItemTemplate>
           </ListBox>
        </StackPanel>

    </StackPanel>
    
</UserControl>
The XAML code is very straight forward. Especially if you have ever worked with Flex, this is the same way of designing Flex application in MXML.

You might noticed that I replaced Grid and used StackPanel all the way for the UI layout. This version of Silverlight doesn't have too many options for UI layout. I used StackPanel with Orientation property (Vertical or Horizontal) as work with HBox or VBox in Flex. Worked just fine.

I used Slider control (code highlighted) to adjust the map zooming. But the feature of the Slider control is very primitive so far. There might be way, but I can't find it to set the sliding step, adjust the ticks, put label on ticks, etc. I know you might be able to do that via Silverlight complex styling template tags. But with Flex slider in mind, it's a bit frustrating to make it works.

I do like the way Silverlight defines content component for the List control (code highlighted). In Flex, it's bit of woks to visually custom the contents of a list or a grid. In Silverlight or MAXL, that can be easily done using DataTemplate. You can mix varies of controls inside the template.

The event handling on UI is simple. The event handling functions are created automatically in the code-behind file page.xaml.cs when event properties are specified. Thus, let's move on to actions.

Fetch Flickr GeoRSS Feed by Tag

All the actually works are defined in the page.xaml.cs file, which is in C#. Connection to Flickr is a HTTP request. In Silverlight, remote connection is asyncnous, just as in Flex.

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(flickrTagURL + feedURL.Text));
request.BeginGetResponse(new AsyncCallback(handleFeed), request);
The above code sends a request to Flickr. The handleFeed function will be called once received the response. flickrTagURL is a constant of the fix URL. feedURL is a input text field for entering a tag. If you are curious, the Flickr URL looks like this:

http://api.flickr.com/services/feeds/geo/?lang=en-us&format=rss_200&tags=sometag

What Flickr returns is GeoRSS feed. That raised a problem. Microsoft does has System.ServiceModel.Syndication package to parse ATOM and RSS feed. But there is no obvious way to parse GeoRSS (please share if you know better). I don't want to use third party parser for this application. Thus, in the handleFeed function, I ended up using XMLReader parsed the feed myself. Not a good way of doing it though.

        void handleFeed(IAsyncResult asyncResult)
        {
             HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
             HttpWebResponse response = 
               (HttpWebResponse)request.EndGetResponse(asyncResult);
 
             XmlReader reader = XmlReader.Create(response.GetResponseStream());
             List<GeoItem> rssItems = new List<GeoItem>();
             GeoItem aItem = null;
             while (reader.Read())
             {
                  switch (reader.NodeType)
                  {
                       case XmlNodeType.Element:
                           String noteName = reader.Name;
                           if (noteName == "item")
                           {
                                aItem = new GeoItem();
                                rssItems.Add(aItem);
                                
                            }
                           else if (noteName == "media:thumbnail")
                           {
                                if (aItem == null) aItem = new GeoItem();
                                reader.MoveToFirstAttribute();
                                aItem.thumbImage = reader.Value;
    				...
That's how I did it, just scan through the feed and pick up what I needed. There is a custom class GeoItem created to store the retrieved information such as item title, description, latitude, longtitute and image URL. In Flex, parsing GeoRSS could be done relatively more easily because E4X handles XML more elegantly. If you are interested in it, I wrote a post awhile ago covered GeoRSS parsing using in Flex E4X way.

In the end, I passed the GeoItem list to the image list mentioned earlier like this:

imageList.ItemsSource = rssItems;

That gets the photo slider (list) populated. However, to test the result, you can't just open the TestPage.html in a browser. You need access your application from a web server, otherwise the photos won't show up. That's the good reason mentioned earlier to have a web server in place for the app. I think there is a security sandbox issue involved but I didn't investigate it any further.

Again, I like the way how Silverlight List control works with contents and data. Now we've got the data, it's about time to deal with the map.

Work with Virtual Earth Map

There are two aspects of integrating Silverlight with Virtual Earth. One is the UI and another one is communication between Silverlight managed code and the map.

Silverlight doesn't come with a map control so that there is no direct way to embed a map inside a Silverlight application. Virtual Earth map is rendered and controlled via JScript inside a HTML page. So, the solution for layout is to put the the map DIV on top of the Silverlight application within the page. Here are the steps to make the whole thing work:

Add the Virtual Earth map to the pageI copied the generated TestPage.html to index.html and worked on it. This is because every time you build your app, the TestPage.html got regenerated, even though nothing changed inside. I don't want loss the JavaScript code put in it. To add a VE map, you need include the VE JavaScript library, put in a map DIV, write a function to load the map, and, call the function at page body onload. Simple, isn't it? Here are the code (assume you know where to put them):
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6"></script>
...
function GetMap()
      {
          map = new VEMap('myMap');
          map.LoadMap();
          map.HideDashboard();
       }
...
<body onload="GetMap();">
...
<div id='myMap'></div>
Lay the map on top of the Silverlight applicationTo do this, you need set couple of parameters on Silverlight. Just add these two to the Silverlight obj definition in the HTML page index.html:
        <param value="transparent" name="background"/>
        <param value="true" name="windowless"/>
Then, define a style for the map DIV to make it show up at where exactly you want it to:
div#myMap {
        position:absolute;
        height:450px;
        left:80px;
        top:172px;
        width:600px;
        border: 2px #B7D8ED;
     }
That's it. Now the map should look just like be part of the Silverlight application.

Communicate with the mapTalking to the map from within Silverlight is mush easier than you would think. First, you need create some JavaScript functions side the HTML page to manipulate the map. Such as a function to add a push pin on the map:
function AddPushpin(title, infobox, lat, lon, zoomLevel)
      {
           var loc = new VELatLong(lat, lon);
           var shape = new VEShape(VEShapeType.Pushpin, loc);
           shape.SetTitle(title);
           shape.SetDescription(infobox);
           map.AddShape(shape);
           map.SetCenterAndZoom(loc, zoomLevel);
       }
From the Silverlight application, all you need to do is call the function and pass in data needed. To call the above add push pin function, in my case, is when the image is clicked in the image list:
   private void imageList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
             GeoItem selectedItem = (sender as ListBox).SelectedItem as GeoItem;
 
             HtmlPage.Window.Invoke("AddPushpin", selectedItem.title, 
                selectedItem.infobox, selectedItem.lat, selectedItem.lon, "7");
             zoomMap.Value = 7;
             curZoom.Text = "7";
         }
All other map control functions work the same way as this one.

To deploy the application, the easiest way is to copy the whole ClientBin directory to a web server. It could be more involved if the application is created as a ASP web application at the first place. But unless you want to the server side Silverlight components to integrate with server side .Net services, keep it in a plain old and good HTML page is a simpler and more portable approach.

This is a simple Silverlight application that gives you a peek on how this new 2.0 beta 1 release works with a RIA developer. You can view this application here and download all the source coder here.

Read more from Moxie Zhang. Moxie Zhang's Atom feed flexria on Twitter

Comments

12 Comments

Joe said:

Great stuff,

Couple of comments. For XML reading you should really use Linq to XML. You can do what you did in 2 or 3 lines of code.
Also, I seem to remember there being better support for Virtual Earth from silverligh. I need to dig up the info.

Finally, did you try using the web server built into Visual Studio (Cassini)?

Moxie said:

Joe, Thanks!
Good point regarding LINQ. Actually if you are .Net developer, go learn and use LINQ.

Yes, please share better VE support if you find it.

No, I didn't use Cassini. Just plain old IIS.

smith said:

I'm download your source code and excutation web page.

but I can't see thumnail.

because I'm my IIS server folder copy and excutation. but I can't see..

why??

Moxie said:

Smith,
Have you tried search something? By default there won't be any search done to popular the slider. BTW, had no clue why the index.html file got deleted from the site. Just put it back.

Thanks

Smith said:

hi moxie

I find my problem.

that's code.

public Page()
{
InitializeComponent();
imageList.ItemsSource = GeoItem.GetSampleGeoItemList();
//this!! imageList.ItemsSource =
feedURL.Text = "silverlight";
}


why not load Flicker resource ?

how to load Flickr XML data in this fuction?

zar said:

hello,
i tried your code, and it's very interesting :)
i'm now able to manage my VEMap from SL controls!
but i have a question :
what about the 'reverse' challenge : for example, to be able to fill SL textboxes from clicks on VE pushpins (VEShape's title --> myTxtB.Text)?
thanks

Joe Holman said:

When I click the view application, all the controls do not work. I have the latest Silverlight Ver 2 Beta 2 installed as of September 15, 2008.

Is there something that needs to change in the code?

Did you updated your nice code to Silverlight 2.0 already?

Daniel said:

I built this site to see what I can do with silverlight and flickr. Take a look at what I have done for using flickr with silverlight mashup. In this site, you can search flickr images and cmpose them in many ways you want to build your competely customized ecards, and you can even search pop songs online and add it to your card, then just send it out, ot save it to edit later.

Daniel said:

I built this site to see what I can do with silverlight and flickr. Take a look at what I have done for using flickr with silverlight mashup. In this site, you can search flickr images and cmpose them in many ways you want to build your competely customized ecards, and you can even search pop songs online and add it to your card, then just send it out, ot save it to edit later.

Daniel said:

sorry, forgot to post the site url
http://www.ecardoo.com

Leave a comment


Type the characters you see in the picture above.

Tag Cloud

Poll: Sci-Fi Movies

What's Your Favorite Sci-Fi Movie of All Time?

Vote | View Poll Results | Read Related Blog Entry

Latest Features

  •     Welcome back to the series. This time we are goings to build a really exciting component that will be used to simply display information about the user. Well, you might say why to we need such a component, is there... Continue Reading
  •    Welcome back to our exciting Facebook ActionScript series. In this article we will discuss one of most important (and most exciting) features of the FB platform, it's the publishing of news. We all know when we log in to facebook,... Continue Reading
  • This article provides 10 tips and best practices (in no particular order) for maximizing the benefits that Dojo can bring to your next project. For a more thorough introduction to Dojo, see the article Dojo: The JavaScript Toolkit with... Continue Reading
  •     The notifications are one of the most interesting (and important) parts of the facebook area. In order to completely understand the Flash side of it, we need to understand the basics of the facebook notification, what it is and how... Continue Reading

Development Series

Get an overview of the tools and technologies that work together to allow developers to build Rich Internet Applications (RIAs) quickly and easily.

facebook icon Facebook Application Development

Anatomy of an Enterprise Flex RIA

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.