Silverlight collaboration demo source code from the MIX essentials keynote

A few people at the MIX essentials event we organized in April requested me to post the source code for the Silverlight demo we gave in the opening keynote. So, here is the code (download at the bottom) along with some explanations of what we implemented. What's also available: a running example hosted at Silverlight Streaming.

image

Check out the recording of the session to view the demo being demonstrated live.

Button style

The "Refresh" button's style is customized by using Application Resources. Application resources allow you to define styles and templates to be applied to controls. Check out this tutorial on styles and templates in Silverlight.

Style and templating defined in App.xaml file:

 <Application.Resources>
        <!-- Button -->
        <Style x:Key="hardComic" TargetType="Button">
            <Setter Property="IsEnabled" Value="true" />
            <Setter Property="IsTabStop" Value="true" />
            <Setter Property="Foreground" Value="#FFFFFFFF" />
            <Setter Property="FontSize" Value="16" />
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="TextAlignment" Value="Center" />
            <Setter Property="TextWrapping" Value="NoWrap" />
<!-- code omitted -->
      </Style>
</Application.Resources>

The custom style is applied to the button by using the key (Page.xaml file):

 <Button x:Name="buttonRefresh" Style="{StaticResource hardComic}" ... />

By applying a custom style and control template, the layout of the button changes from

image

to

image 

Bubble animation

The bubbles in the test tube were created in Expression Blend 2.5. The animation is created by moving the bubbles from the bottom of the test tube to the limit of the pink liquid. This is done in a Storyboard containing several keyframes for the different bubbles. A different path is used for each bubble so that the effect is like real bubbles are coming up. At the end of the storyboard, Opacity of each bubble is set to 0% so that these are no longer visible. We also set the Repeat behavior of the storyboard to Forever so that the animation keeps on playing once its started.

image  (click to enlarge)

Thanks to Stijn for the animation!

Loading images through REST

Photos are loaded by accessing the Flickr search REST service. This is done by creating a WebClient object, accessing the service asynchronously and then parsing the returned XML to load the photos on the surface:

 private void LoadPictures()
        {
            // Initialize Flickr URI
            string tags = "mixessentialsbe";
            string key = "hidden";
            string flickrApi = string.Format("https://api.flickr.com/services/rest/
?method=flickr.photos.search&api_key={0}&tags={1}", key, tags);


            // Asynchronous call to REST Service
            WebClient rest = new WebClient();
            rest.DownloadStringCompleted += new DownloadStringCompletedEventHandler
(rest_DownloadStringCompleted);
            rest.DownloadStringAsync(new Uri(flickrApi));           
           
        }

void rest_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
 {
       if (!_photosLoaded && (0 != Width) && (0 != Height))
       {
            //... some code omitted

            if (doc.Element("rsp").Attribute("stat").Value == "ok")
            {
                // Current Page Logic
                int totalPages = Convert.ToInt32(doc.Descendants("photos").Single().
Attribute("total").Value);
                if (_pageIndex >= totalPages)
                    _pageIndex = 0;

                // Get Photo collection using Linq to XML
                var photos = (from results in doc.Descendants("photo")
                              select new
                              {
                                  id = results.Attribute("id").Value.ToString(),
                                  farm = results.Attribute("farm").Value.ToString(),
                                  server = results.Attribute("server").Value.ToString(),
                                  secret = results.Attribute("secret").Value.ToString()
                              }).Skip(_pageIndex * 10).Take(10);
                // Add a photo control for each Photo returned
          foreach (var photo in photos)
           {
             url = string.Format("https://farm{0}.static.flickr.com/{1}/{2}_{3}_m.jpg",
                photo.farm, photo.server, photo.id, photo.secret);
             new Photo(this, this.SurfaceLayoutRoot, new Uri(url));
              }
              _photosLoaded = true;
            }
      }
}

I recommend reading Gill's tutorial on Silverlight 2 data and services for detailed information on accessing services using Silverlight.

The Surface-like experience

To show the photos we reused some sample code from the Community samples at silverlight.net: Silverilght Surface sample.

This example includes a custom Photo class that we have reused and slity adapted to fit the new parent object (our Page.xaml). It adds a really cool experience to displaying the photos.

image

Getting the source code to work: Flickr API key

You do need to request your own API key at Flickr and add it to the code before being able to run the code locally. Sign-up for a key at the Flickr site and then change the key in Page.xaml.cs file:

  private void LoadPictures()
        {
            // Initialize Flickr URI
            string tags = "mixessentialsbe";
            //todo: create your own API key at Flickr and copy here:
            string key = "flickr api key here"; 
            string flickrApi = string.Format("https://api.flickr.com/services/rest/?
method=flickr.photos.search&api_key={0}&tags={1}", key, tags);

        //rest of code omitted...     
           
        }

Add the key, rebuild and the app should run locally.

Download the source code

Code can be downloaded from my Skydrive.

Technorati Tags: mixessentialsbe,silverlight 2,expression,blend,visual studio