SILVERLIGHT

Get Started Building A Deeper Experience Across The Web

Laurence Moroney

This article is based on a prerelease version of Silverlight. All information herein is subject to change.

This article discusses:

  • An introduction to Silverlight and XAML
  • Building a simple Silverlight app
  • Generating Silverlight apps dynamically on the server
  • Creating a XAML service
This article uses the following technologies:
Silverlight, XAML, JavaScript

Code download available at: Silverlight 2007_06.exe(300 KB)

Contents

Introducing Silverlight
XAML Overview
Inside the XAML
Transformations, Media, and Animations
A Simple Silverlight Application
Server Applications with Silverlight
Building a Weather App
Defining the Fade-In Animations
Creating a XAML Service
Delivering XAML to the Silverlight Front End
Summary

A key component in the Microsoft strategy for next-generation Web development is a new technology named Microsoft® Silverlight™, formerly code-named "WPF/E." Designed to bring the Windows® Presentation Foundation experience to the Web, Silverlight provides rich, immersive content that fits seamlessly with the rest of the Web development environment, including ASP.NET AJAX.

To reach the Web community at large, Silverlight needs to run successfully on a number of popular operating systems and in the most popular browsers. As a result, the first release supports the Firefox and Safari browsers running on Mac OS X as well as Firefox and Internet Explorer® running on Windows. More operating systems and browsers should be supported as the product evolves. In addition to these capabilities, Silverlight is also completely self-contained and has no dependencies on other products such as Windows Media® Player for video playback or the Microsoft .NET Framework 3.0 for XAML parsing.

In this article, you get a high-level overview of the architecture of Silverlight, and get hands-on experience building several Silverlight applications, starting with a basic Hello World application. I then walk you through building a simple media player. You also see how, while Silverlight is a client-side technology, it fits into a larger server-oriented picture, including the ability to be used on servers running PHP or Java.

Introducing Silverlight

At its core, Silverlight is a browser plug-in that renders XAML, exposing its internal Document Object Model (DOM) and event model to the browser in a scriptable manner. Thus, a designer can put together a XAML document containing graphics, animations, and timelines and a developer can hook these up to code in a page to implement functionality. As XAML is based on XML, the document defining the UI that gets downloaded to the client is text-based and thus friendly to search engines and firewalls. In addition, the XAML may be assembled and emitted at run time by a server application, providing not only a rich graphical experience, but also a highly customizable and dynamic one.

The anatomy of a simple Silverlight application, using a static XAML file defining its UI and JavaScript for event handling, is shown in Figure 1. The browser instantiates the plug-in and, as part of this process, loads the XAML file. Events within this file, such as clicking on a button, are captured by the browser and processed by JavaScript. As the DOM of the Silverlight content is exposed, the JavaScript code can also dynamically update the Silverlight contents, changing the state of the rendered content.

Figure 1 Sample App

Figure 1** Sample App **

The architecture that supports the Silverlight application is shown in Figure 2. The main programming interface is the JavaScript DOM API. This allows you to respond to events raised within the Silverlight XAML (such as when content has finished loading or when an animation is complete). You can also call methods to manipulate the presentation (such as starting an animation or pausing video playback). Underneath this is the XAML parsing engine. The parser creates the in-memory XAML DOM for use by the presentation core, which handles the rendering of the graphics and animations defined by the XAML. In addition, the runtime contains the codecs necessary for playback of WMV, WMA, and MP3 multimedia content.

Figure 2 Silverlight Architecture

Figure 2** Silverlight Architecture **

Finally, the runtime contains the presentation core, which manages the rendering process. This presentation runtime is built into a browser plug-in that supports several flavors of Windows as well as Mac OS X, using any of several browsers as discussed previously. The end result is a self-contained graphics and media rendering engine that may be plugged into the browser and scripted via JavaScript.

XAML Overview

XAML is an XML-based language that may be used to define graphical assets, user interfaces, behaviors, animations, and more. It was introduced by Microsoft as the markup language used in Windows Presentation Foundation, a desktop-oriented technology that is part of the .NET Framework 3.0. It was designed to help bridge the work between designers and developers in creating applications.

Traditionally, designers used one suite of tools and resources for creating an application, and developers used their own separate tools. The mismatch between toolsets had the potential to adversely affect the resulting application. Microsoft introduced the new Expression suite of tools, particularly Microsoft Expression® Design and Microsoft Expression Blend, to allow design professionals to put together graphical artifacts and user interfaces respectively, expressing the end result as XAML, which a developer can then take and build an application from.

The XAML used by the first release of Silverlight differs from that used by Windows Presentation Foundation in that the former is a Web-oriented subset of the full XAML available for the desktop. As such, if you are familiar with Windows Presentation Foundation XAML, you’ll notice some things missing such as the <Window> tag, page resources, data binding, and the rich control model.

In XAML you define elements using XML tags. At the root level of every Silverlight document is a Canvas tag, which defines the space on which UI elements will be drawn. This Canvas should contain the XML namespace declarations that Silverlight needs.

<Canvas
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>
</Canvas>

A Canvas can have one or more children, including child Canvases that can create their own children. Children of a Canvas have relative positions to their parent Canvas, not to the root Canvas. Here’s an example of a Canvas containing a Rectangle, and the rectangle is placed 25 pixels from the top-left corner of its parent.

<Canvas Width=”250” Height=”200”>
  <Rectangle Canvas.Top=”25” Canvas.Left=”25” 
       Width=”200” Height=”150” Fill=”Black” />
</Canvas>

Inside the XAML

Silverlight XAML supports a number of shapes that can be orchestrated into complex objects. The basic supported shapes are Rectangle, Ellipse, Line, Polygon, PolyLine, and Path. Most of these are self-explanatory. PolyLine allows you to define a series of joined line segments. Path allows you to define a nonlinear path (like a scribble) across the Canvas.

Brushes determine how objects are painted on the screen. Their contents are painted using a Fill and their outlines are painted using a Stroke. There are solid-color brushes, gradient brushes, and image brushes. Solid color brushes are implemented using either a fixed color on the fill attribute (such as Fill="Black" used in the previous example) or using SolidColorBrush as an attached property like this:

   <Rectangle Canvas.Top=”25” Canvas.Left=”25” 
          Width=”200” Height=”150”>
      <Rectangle.Fill>
         <SolidColorBrush Color=”Black” />
      </Rectangle.Fill>
   <Rectangle>

Colors can be defined by name (141 named colors are supported) or by hex RGB definition.

Gradient brushes are implemented by defining a gradient range and a number of gradient stops across a normalized space. For example, say you wanted a linear gradient to move from right to left, changing from black to white through the shades of gray as you go. You would specify a gradient stop at 0 (the beginning of a normalized line) that is black, and a gradient stop at 1 (the end of a normalized line) that is white. Silverlight will then paint the gradient for you. Gradients may also be painted in two dimensional space, with a normalized rectangle defining the space (0,0 is top-left and 1,1 is bottom-right). So to define a rectangle filled with a 2D gradient with red in the top-left, black in the bottom-right, and a smooth gradient between them, you would use XAML like this:

<Rectangle Width=”200” Height=”150” >
  <Rectangle.Fill>
    <LinearGradientBrush StartPoint=”0,0” EndPoint=”1,1”>
      <LinearGradientBrush.GradientStops>
        <GradientStop Color=”Red” Offset=”0” />
        <GradientStop Color=”Black” Offset=”1” />
      </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Rectangle.Fill>
</Rectangle>

Objects may also be painted using ImageBrushes, and the image will be clipped or stretched as appropriate. So, for example, you can specify to fill an Ellipse using an ImageBrush with XAML like this:

<Ellipse Width=”200” Height=”75” >
  <Ellipse.Fill>
    <ImageBrush ImageSource=”http://.../logo.jpg” /> 
  </Ellipse.Fill>
</Ellipse>

Text can be rendered in XAML using the TextBlock tag. This gives you control over aspects of the text such as content, font, size, wrapping and more. Here are some examples:

<TextBlock>Hello</TextBlock>

<TextBlock FontSize=”18”>Hello</TextBlock>

<TextBlock FontFamily=”Courier New”>Hello</TextBlock>

<TextBlock TextWrapping=”Wrap” Width=”100”>
  Hello there, how are you?
</TextBlock>

In addition, Silverlight supports keyboard events that can be used to implement text input. You can define a keyboard event (KeyDown or KeyUp) on the root element, and use the event arguments to derive which key was pressed.

Transformations, Media, and Animations

XAML allows you define a number of transformations on objects. RotationTransform rotates the element through a defined number of degrees, ScaleTransform can be used to stretch or shrink an object, SkewTransform skews it in a defined direction by a defined amount, TranslateTransform moves an object according to a defined vector, and MatrixTransform can combine all of the above.

Transformations may be grouped so that an object has a number of transformations placed on it by defining those transformations as part of the group. Figure 3 shows an example. In this case, there are three Ellipses in the Canvas. As the transform is defined at the Canvas level, each one of these Ellipses will be rotated and scaled.

Figure 3 Multiple Transformations

<Canvas xmlns=”...” xmlns:x=”...”>
  <Canvas.RenderTransform>
    <TransformGroup>
      <RotateTransform Angle=”-45” CenterX=”50” CenterY=”50”/>
      <ScaleTransform ScaleX=”1.5” ScaleY=”2” />
    </TransformGroup>
  </Canvas.RenderTransform>
  <Ellipse Width=”100” Height=”100” Fill=”Yellow” />
  <Ellipse Canvas.Top=”25” Canvas.Left=”25” Width=”10” Height=”10” 
           Fill=”Black” />
  <Ellipse Canvas.Top=”25” Canvas.Left=”65” Width=”10” Height=”10” 
           Fill=”Black” />
</Canvas>

Audio and video content is controlled using the MediaElement tag. This tag takes a source attribute that points to the media to be played. An object defined using this tag provides many methods and events that control media playback. Later in this article, you’ll see an example of a simple media player that is built using XAML, with JavaScript enabling the user interaction (play, pause, stop, and so on). Defining a MediaElement is straightforward:

<Canvas xmlns=”...” xmlns:x=”...”>
   <MediaElement Source=”xbox.wmv” /> 
</Canvas>

Animations in XAML are implemented by defining how properties should be changed over time via a timeline. Animation definitions are contained within a Storyboard. There are a number of different types of animation, including DoubleAnimation, which changes numeric properties; ColorAnimation, which changes colors and brushes; and PointAnimation, which changes two-dimensional values. These animations can either be linear or keyframe based. In the case of a linear animation, the animation changes smoothly along the defined timeline. With a keyframe-based animation, the animation can move between discrete values along the way.

Figure 4 shows an example of a simple animation that changes the width of a circle over time. The AutoReverse property is set to True, instructing the engine to continue the animation, reversing along the way so the circle goes from wide to narrow to wide instead of repeating a wide to narrow transformation.

Figure 4 A Simple Animation

<Canvas xmlns=”...” xmlns:x=”...”>
  <Canvas.Triggers>
    <EventTrigger RoutedEvent=”Canvas.Loaded”>
      <BeginStoryboard>
        <Storyboard> 
          <DoubleAnimation 
            Storyboard.TargetName=”theCircle” 
            Storyboard.TargetProperty=”Width” 
            From=”200” To=”1” Duration=”0:0:2”        
            AutoReverse=”True”/>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Canvas.Triggers>
  <Ellipse x:Name=”theCircle” Width=”100” Height=”100” Fill=”Yellow” />
</Canvas>

A Simple Silverlight Application

With Visual Studio 2005, you can use an application template for Silverlight (part of the Silverlight SDK download) that allows you to easily build applications for Silverlight. For this article I used the Visual Web Developer™ Express application, which is available for download from MSDN®.

This example is a very simple media player that plays WMV video content. It uses a Channel 9 video (channel9.msdn.com), but you can change this to play whatever video you prefer. The XAML is pretty straightforward and can be seen in its entirety in Figure 5. For the sake of simplicity, TextBlock elements are used for the Play, Stop, and Pause buttons.

Figure 5 A Simple Media Player

<Canvas 
    xmlns=”http://schemas.microsoft.com/client/2007”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
    Loaded=”javascript:root_Loaded”>

    <MediaElement 
        x:Name=”mPlayer” Width=”640” Height=”400” 
        Source=”http://download.microsoft.com/download/6/5/2/6527a090-aef4-4ed2-8d7e-8946e94257a0/WM_IN_Sumit_Chauhan.wmv” />

    <TextBlock Canvas.Top =”0” Text=”Play” 
        MouseLeftButtonDown=”javascript:PlayVideo”>
    </TextBlock>
    <TextBlock Canvas.Top =”16” Text=”Stop” 
        MouseLeftButtonDown=”javascript:StopVideo”>
    </TextBlock>
    <TextBlock Canvas.Top =”32” Text=”Pause” 
        MouseLeftButtonDown=”javascript:PauseVideo”>
    </TextBlock>
</Canvas>

The MediaElement tag is used to define the video. It is given a name, mPlayer, and has its dimensions set to 640×400. The Source tag is pointed at a WMV video that’s hosted as a download on the Microsoft Web site.

Next are the three TextBlock elements that are used to define the Play, Stop, and Pause buttons. These buttons are spaced vertically in the top left-hand side of the canvas. Note that Canvas.Left isn’t being set, and it defaults to 0. These TextBlock elements define a JavaScript event handler to fire when they are clicked (MouseLeftButtonDown). When the mouse button is pressed on them, Silverlight passes the event up to the browser, where it is captured and handled by JavaScript.

Let’s now put together an application that uses this XAML and implements the JavaScript event handlers using Visual Web Developer Express. For this to work, you’ll need the silverlight.js file, which you can get from the SDK download for Silverlight or from any of the Silverlight samples in the sample download site on MSDN.

Using Visual Web Developer Express, create a new Web site. Within this site, create a folder called \js and add the silverlight.js file to it. Right-click the \js folder and select Add New Item. Select JScript File in the new file dialog, and call it eventhandlers.js.

Next, right-click on the project in Solution Explorer, click Add New Item, and create a new XML file called videoplayer.xaml. Populate it with the XAML listed in Figure 5.

Finally, add a new HTML page to the project and call it Default.htm. Edit the HTML page so that it loads the JavaScript libraries and uses them to create an instance of the Silverlight player that will render the XAML content. Figure 6 shows the full source code for Default.htm.

Figure 6 Default.htm Loads the Media Player

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” 
    “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<head>
    <title>Untitled Page</title>
    <script type=”text/javascript” src=”js/silverlight.js”></script>
    <script type=”text/javascript” src=”js/eventhandlers.js”></script>
</head>
<body>
    <form>
         <div id=”AgControl1Host” style=”background:#FFFFFF”>     
            <script type=”text/javascript”>
                Sys.Silverlight.createObjectEx(
                    {source: ‘videoplayer.xml’, 
                     parentElement:’AgControl1Host’, 
                     Id:’AgControl1’, 
                     properties:{
                         width:’1024’, 
                         height:’530’, 
                         background:’white’, 
                         isWindowless:’false’, 
                         framerate:’24’, 
                         version:’0.8.5’}, 
                     events:{onError:null, onLoad:null, 
                         onNotInstalled:null}, 
                     context:null});
            </script>
         </div>
    </form>
</body>
</html>

The script tags at the top of the page import your JavaScript libraries, silverlight.js and eventhandlers.js. The silverlight.js library manages the downloading and instantiation of the Silverlight plug-in. It has the browser and OS abstractions so that you don’t need to worry about them; you can just implement a new Silverlight control with the Sys.Silverlight.createObjectEx function. The Silverlight plug-in itself should be within a DIV block that is given an ID. In this case, the DIV containing the plug-in is called AgControl1Host. You’ll use this ID when instantiating the Silverlight content.

The Silverlight plug-in is instantiated by creating a new instance of the Silverlight control, passing it a bunch of parameters to construct it. See the Silverlight SDK for more information on these parameters.

The final step is to implement the JavaScript functions that handle the events raised by clicking on the Play, Stop, and Pause buttons. This code should be put in eventhandlers.js.

function PlayVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Play();
}
function PauseVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Pause();
}
function StopVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Stop();
}

In the XAML, the Stop TextBlock defined the MouseLeftButtonDown attribute to point to JavaScript:StopVideo. You implement the function by creating a JavaScript function of the same name that takes sender and args parameters. You can use the findName function in Silverlight to find an element within its DOM that matches the named parameter. Therefore, to stop the video from playing, you use the findName API to find the MediaElement. In the XAML, this element was called mPlayer. The findName API will return a reference to this object that you can load into a JavaScript var. Now that you have a reference, you can simply call its Stop method to stop the video playing. The Play and Pause functionality is similar.

And that’s it! A simple video player put together with Silverlight in no time flat. Run your application and you’ll see something like Figure 7.

Figure 7 The Simple Video Player

Figure 7** The Simple Video Player **(Click the image for a larger view)

This is all very nice if you want to hardcode the URI of the video into your XAML, but that’s not really the most feasible use case. Let’s take a look at changing this from a static HTML page into an active Web form that can accept the video as a parameter.

The first step is to remove the reference to the media file from the XAML. Change the MediaElement in your XAML to remove the Source attribute. It should look like this when you’re finished:

<MediaElement x:Name=”mPlayer” Width=”640” Height=”400”/>

Next, create a new Web Form (ASPX) named VideoPlayer.aspx in your application. This form should instantiate a Silverlight control sourced with videoplayer.xaml, as was done in Figure 6. In addition, it should contain the following JavaScript code:

<script type=”text/javascript”>
  function root_Loaded(sender,args) {
    var mPlayer = sender.findName(“mPlayer”);
    mPlayer.Source =
      “<% Response.Write(Request.Params[“VideoURI”]); %>”;
    mPlayer.Play();
}
</script>

The XAML contains an event declaration for an event to fire when the Canvas loads. This is captured by the root_Loaded event handler in JavaScript. This function uses ASP.NET to pull the VideoURI off the HTTP request on the server, and uses the VideoURI to fill in the JavaScript function, thus setting the video source. When the page executes, the video (at the VideoURI parameter) will be rendered by Silverlight. Be aware that this very simple example doesn’t have any error handling or filtering, which you should add if you want this type of functionality in your apps.

Note that when you call this page with a URI like this:

http://localhost/MSDN1/
VideoPlayer.aspx?videouri=xbox.wmv

ASP.NET will emit a page containing a JavaScript block that looks like this:

   <script type=”text/javascript”>
     function root_Loaded(sender,args)
     {
       var mPlayer = 
         sender.findName(“mPlayer”);
       mPlayer.Source = “xbox.wmv”;
       mPlayer.Play();
     }
   </script>

This JavaScript then loads the xbox.wmv file into the MediaElement and Silverlight plays the video. This shows that using server-side active pages (ASPX, PHP, or Java) can greatly enhance your Silverlight end user experiences by making them much more flexible.

Server Applications with Silverlight

It’s hardly fair to think of Silverlight solely as a client technology meant to embed rich content in the browser. Such rich content is already possible through use of closed plug-ins built as Java Applets, ActiveX® controls, or Flash applications. By contrast, Silverlight is an open technology in the sense that the UI is defined in text-based XAML and the programmability is achieved using JavaScript. This allows developers to easily build applications that interact with back-end servers.

For example, consider a weather application. If you wanted to produce a weather application on the client-side, you could build a Java applet, ActiveX control, or Flash application that consumes a Web service and then deploy this applet to the client. However, this increases the communication needs between the client and the server. What if this data source is a paid-subscription service? The person deploying the application has to take on the job of authenticating licenses for any clients accessing the data service, and that takes time away from building domain-specific business logic.

However, if the application can be assembled on the server side and all data is passed back to the client, then this work is alleviated. By using a tool such as Expression Blend, a template for the application’s user interface can be assembled and expressed as XAML. The developer, at runtime, then takes the relevant data and inserts it into the template, returning the finished XAML to the client that renders it. No logic or connectivity is required on the client side (other than the initial connectivity to the server that serves it up, of course), and the deployment and management of the client is thus kept relatively easy.

Building a Weather App

In this section, you’ll see how to build a simple XAML file that implements a weather application (see Figure 8). The finished weather application will render three days worth of temperature forecasts for a specific ZIP Code that is passed to the application as a parameter on its address within the browser. It will also render a graphical representation of the weather, the correct dates, the name of the location specified by the ZIP Code, and animations of the weather data. The complete listing of the XAML for the weather application is available from the MSDN Magazine Web site.

Figure 8 Silverlight Weather App

Figure 8** Silverlight Weather App **(Click the image for a larger view)

At the top of the document is the opening Canvas tag. This is a basic container on which you will draw your objects. You aren’t limited to one Canvas, and it makes sense for you to group your related elements together using a Canvas. So, for example, each day contains a graphic, a high temperature, a low temperature, and various labels, and all of this is collected into a XAML template. Figure 9 is an example of one particular day. In this case, the Canvas contains a number of TextBlocks and an Image control. This canvas is given a name cnv2 and is placed on screen with an opacity of 0 (meaning that it is initially invisible). Its height, width, left, and top are set to put it in a specific location on the screen.

Figure 9 Elements Collected in a Day

<Canvas x:Name=”cnv2” Width=”624” Height=”101” Opacity=”0” 
        Canvas.Left=”8” Canvas.Top=”165”>

<TextBlock x:Name=”lblDate2” Width=”513” Height=”26” Canvas.Left=”97” FontFamily=”Tahoma” FontSize=”20” FontWeight=”Bold” Foreground=”#FF24AB46” Text=”Wednesday, December 18, 2006” TextWrapping=”Wrap”/>

<TextBlock x:Name=”lblHigh2” Width=”70” Height=”59” Canvas.Left=”112” Canvas.Top=”30” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FFF64F12” Text=”27” TextWrapping=”Wrap”/>

<TextBlock x:Name=”lblDegHigh2” Width=”62” Height=”59” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FFF64F12” Text=”°F” TextWrapping=”Wrap” Canvas.Left=”172” Canvas.Top=”30”/>

<TextBlock x:Name=”lblLow2” Width=”71” Height=”59” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FF444DB5” Text=”27” TextWrapping=”Wrap” Canvas.Left=”265” Canvas.Top=”30”/>

<TextBlock x:Name=”lblDegLow2” Width=”67” Height=”59” FontFamily=”Tahoma” FontSize=”48” FontWeight=”Bold” Foreground=”#FF444DB5” Text=”°F” TextWrapping=”Wrap” Canvas.Left=”327” Canvas.Top=”30”/>

<Image x:Name=”imgWeather2” Width=”97” Height=”87” Canvas.Top=”4” Source=”http://www.nws.noaa.gov/weather/images/fcicons/ra80.jpg” Stretch=”Uniform”/>

</Canvas>

The TextBlocks are used to render text in Silverlight. There are a number of them here, some used as hardcoded labels such as the "°F" labels that are stored in the TextBlocks called lblDegHigh2 and lblDegLow2. See the x:Name attribute to find the name.

The TextBlocks called lblDate2, lblHigh2, and lblLow2 contain placeholder information—right now they are hardcoded for specific data and temperature, but your ASP.NET code will override these with the live date and temperatures for the specified ZIP Code.

Defining the Fade-In Animations

A Canvas node supports triggers that fire off actions in response to an event. In this case, the Canvas.Triggers are specified to occur when the page is loaded as shown here:

<Canvas.Triggers>
  <EventTrigger RoutedEvent=”FrameworkElement.Loaded”>
    <BeginStoryboard>
...

Thus, when the page gets loaded, the triggers will fire and an animation Storyboard will begin. The animation Storyboard defines the animation behaviors. Here is the animation that is used on the Canvas (containing the text placeholders and graphic for a specific day’s weather) called cnv1:

<DoubleAnimationUsingKeyFrames BeginTime=”00:00:00”  
    Storyboard.TargetName=”cnv1” 
    Storyboard.TargetProperty=”(UIElement.Opacity)”>
  <SplineDoubleKeyFrame KeyTime=”00:00:00” Value=”0”/>
  <SplineDoubleKeyFrame KeyTime=”00:00:01” Value=”1”/>
</DoubleAnimationUsingKeyFrames>

The animation type is a DoubleAnimationUsingKeyFrames. You will be amending the opacity (defined by UIElement.Opacity) of the Canvas and its children from 0 to 1, causing it to fade in over a period of time. The time is defined by the keyframes associated with the animation.

When the XAML renders, the Storyboard will begin, causing the first element to fade in from opacity 0 to opacity 1 between the beginning of the rendering (time of 0 seconds) until 1 second later. Look at the XAML and you’ll see that the other Canvasses fade in between 1 and 2 seconds, and between 2 and 3 seconds respectively, giving an effect of each one appearing in turn.

XAML is a form of valid XML, so elements can be named with attributes, and from that naming they can be addressed. So, for example, the placeholder element for the high temperature for Day One looks like this:

<TextBlock x:Name=”lblHigh1” Width=”67” Height=”59” 
        Canvas.Left=”112” Canvas.Top=”30” FontFamily=”Tahoma” 
        FontSize=”48” FontWeight=”Bold” Foreground=”#FFF64F12” 
        Text=”27” TextWrapping=”Wrap”/>

This TextBlock is given the name lblHigh1. The service (which you will see in the next step) uses an XMLDocument to load the template XAML, find the node with this name, and change its text property with C# code that looks like this:

string xpath = “//d:TextBlock[@x:Name=’lblHigh1’]”;
xNode = xmlDoc.SelectSingleNode(xpath, mng);
string high = myResults[n - 1].MaxTemperatureF;
xNode.Attributes[“Text”].Value = high;

Creating a XAML Service

When you use Silverlight in a Web page, one of the parameters that the control takes is the location of the XAML to render. In this case, the XAML is dynamic, changing based on the ZIP Code for which the weather is being requested. As such, you’ll create a Web application that generates and returns the XAML, and the page that renders it will refer to this page. This is the first step in building this Silverlight application.

Using Visual Studio®, create a new Web Project. Add a \js folder containing silverlight.js, just like you did with the earlier video player. Add a new Web reference to the project, referencing the Web service defined at:

http://www.webservicex.net/WeatherForecast.asmx?WSDL

Give the service the name weatherservice. Add a new Web Form to the project and call the Web Form XAMLSource.aspx. Select the Add Code as a Separate Page option. Make sure that the top of the code page has the following set of using directives:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.XPath;

For the rest of this section, you’ll be adding code to the Page_Load event handler on XAMLSource.aspx. First, load the template (called Scene.xaml) into an XMLDocument object:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath(“Scene.xaml”));

Next, set up the read parameter. You’ll be calling the page using a query string parameter specifying the required ZIP Code:

http://server/XamlSource.aspx?ZIP=<something>

To retrieve the parameter, use this code:

string strZip = “98052”;
if (Request.Params[“ZIP”] != null)
    strZip = Request.Params[“ZIP”];

This initiates the string that will hold the parameterized ZIP locally, and sets it to a default if it isn’t passed in as part of the HTTP Request. Next, create the call to the Web service that serves the weather information:

weatherservice.WeatherForecast myWeather = new 
    weatherservice.WeatherForecast();

weatherservice.WeatherForecasts myForecast =   
    myWeather.GetWeatherByZipCode(strZip);

weatherservice.WeatherData[] myResults = myForecast.Details;

This code creates an instance of the Web service proxy (created for you by Visual Studio when adding a reference to the service’s WSDL) that it calls myWeather. The Web service returns data in the WeatherForecasts data structure, so it creates an instance of this data structure (called myForecast) by calling the GetWeatherByZipCode method on the service, passing it a string. The Details member of the forecast object is an array of WeatherData types, so the variable myResults is set up as an instance of this.

The next step is to initialize the XMLDocument for searching using XPath. As the XML uses the XAML schema as a namespace for some of the elements (prefixed with an x, such as x:Name), you’ll need to define a namespace for all of the elements in the page, even those that aren’t prefixed. For example, you cannot search for nodes matching the XPath //TextBlock, but you can specify the default namespace to have a new prefix (in this case d for dummy), and search for the default nodes using this prefix, so //d:TextBlock will work. Here’s the code:

NameTable myn = new NameTable();
XmlNamespaceManager mng = new XmlNamespaceManager(new NameTable());
mng.AddNamespace(“d”,
    “http://schemas.microsoft.com/winfx/2006/xaml/presentation”);
mng.AddNamespace(“x”, “http://schemas.microsoft.com/winfx/2006/xaml”);

Now that you can use XPath, you can find the node that contains the town name and change its Text property to be the name of the town that the service identified at that ZIP Code.

XmlNode xNode = xmlDoc.SelectSingleNode(
    “//d:TextBlock[@x:Name=’lblTownName’]”, mng);

xNode.Attributes[“Text”].Value = 
    myForecast.PlaceName + “,” + myForecast.StateCode;

Similarly, you can loop through the next three days, find the placeholder nodes that contain the desired locations for their values, and prune the correct values into the XML with the code shown in Figure 10.

Figure 10 Updating Weather Information

string strXPath = “”;
string strDate = “”;
string strHigh = “”;
string strLow = “”;
string strWeatherURL = “”;

for (int n = 1; n <= 3; n++)
{
  strXPath = “//d:TextBlock[@x:Name=’lblDate” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strDate = myResults[n - 1].Day;
  xNode.Attributes[“Text”].Value = strDate;

  strXPath = “//d:TextBlock[@x:Name=’lblHigh” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strHigh = myResults[n - 1].MaxTemperatureF;
  xNode.Attributes[“Text”].Value = strHigh;

  strXPath = “//d:TextBlock[@x:Name=’lblLow” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strLow = myResults[n - 1].MinTemperatureF;
  xNode.Attributes[“Text”].Value = strLow;

  strXPath = “//d:Image[@x:Name=’imgWeather” + n.ToString() + “’]”;
  xNode = xmlDoc.SelectSingleNode(strXPath, mng);
  strWeatherURL = myResults[n - 1].WeatherImage;
  xNode.Attributes[“Source”].Value = strWeatherURL;
}

Now that you’ve fully populated your XML document with the template and the correct data, the last step is to return it to the caller. You do this by setting the MIME type and writing the contents of the XMLDocument object directly to the response stream, like so:

Response.ContentType = “text/xml”;
Response.Write(xmlDoc.InnerXml);

Next, remove the placeholder HTML that Visual Studio gave you in your ASPX page. Remove everything except the first line from the ASPX file. It should look something like the following code when you’re finished:

<%@ Page Language=”C#” AutoEventWireup=”true”    
         CodeFile=”XamlSource.aspx.cs” Inherits=”_Default” %>

The final step is to add a new XML file to your solution and call it Scene.xaml. You will have seen this file being referred to in the code earlier. Get the full weather XAML and paste it into this file. You can now execute the page, and you should see the XAML returned by the XAMLSource.aspx page in your browser.

Delivering XAML to the Silverlight Front End

In the previous steps, you built the template XAML, and then built a Web form that takes this XAML, consumes a Web service, and puts the results of the Web service call into the XAML at the correct place. The next step is to serve up a page that contains the Silverlight control and points it at this XAML service.

Open up the Web site that you used in the previous sections and add a new Web form called Default.aspx. Modify the HTML Code on Default.aspx to look like Figure 11.

Figure 11 More Changes to Default.aspx

<%@ Page Language=”C#” AutoEventWireup=”true”
    CodeFile=”Default.aspx.cs” Inherits=”_Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
 “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
    <title>Weather</title>
    <meta http-equiv=’Content-Type’ 
          content=”text/html; charset=windows-1252”/>
    <script type=”text/javascript” src=”js/silverlight.js”></script>
</head>
<body>
<div id=”AgControl1Host” style=”background:#FFFFFF”>     
    <script type=”text/javascript”>
        Sys.Silverlight.createObjectEx(
            {source: ‘WeatherSite/XamlSource.aspx?ZIP=<%
                        if (Request.Params[“ZIP”] == null)
                            Response.Write(“98052”);
                        else
                           Response.Write(Request.Params[“ZIP”]);
              %>’, parentElement:’AgControl1Host’, Id:’AgControl1’, 
              properties:{width:’1024’, height:’530’, 
                  background:’white’, isWindowless:’false’, 
                  framerate:’24’, version:’0.8.5’}, 
              events:{onError:null, onLoad:null, onNotInstalled:null},
                  context:null});
    </script>
</div>
</body>
</html>

The important part of this is in the call to Silverlight.createObjectEx, where the static videoplayer.xaml has been replaced with a call to the XAML source application, passing it the parameter that this Default.aspx page received for the ZIP Code:

“WeatherSite/XamlSource.aspx?ZIP=<%
    if (Request.Params[“ZIP”] == null)
        Response.Write(“98052”);
    else
        Response.Write(Request.Params[“ZIP”]);
%>” 

This takes the request parameter to this page and appends it to a URL, which will call the XamlSource page that you created in the last step. This will then make a call to the XamlSource, passing the ZIP Code, and getting a XAML document back, which is then rendered by Silverlight. The results of running Default.aspx?ZIP=90210 can be seen in Figure 8.

Summary

In this article, you got a deep introduction to Silverlight. You also looked at some applications that go beyond just parroting "Hello, World," such as how XAML is used to construct user interfaces, how it can be tied to JavaScript for interactivity, and how you can move beyond a pure client paradigm into a server-based one to make your applications more flexible. Using this methodology, you saw how to create a simple video player that accepts the URI of a video stream and plays it back, making it ideal for use in scenarios such as blogs.

Additionally, you learned how to build a data-aware application, in the form of a weather monitor that has a very simple client distribution model. You simply had the Silverlight component call the server for the correct XAML and render it, forming a rich, thin client.

While ASP.NET and the Microsoft stack represent one very productive platform for building Web applications such as this, the download for this article also contains a Java version of this application. This version offers the same functionality as the ASP.NET version—consuming the Web service to get the data and then loading the XAML into an XML Document DOM. It then fishes out the appropriate nodes for the template data and replaces their values with those from the Web service before writing the finished XAML out as a URI. The JSP (not listed) is then constructed to reference the URL of this servlet to render the XAML using Silverlight.

The road is just beginning for Silverlight on the Web. With the richness of a XAML rendering engine, and the flexibility of using standard Web development technologies, Silverlight is something well worth adding to your developer toolbox. For more information, take a look at the Silverlight developer center on MSDN.

Laurence Moroney is a Silverlight technology evangelist at Microsoft. He is author of nine computing books and over 100 technology articles, including the upcoming Programming Web.NEXT from Microsoft Press. When not writing articles or code, he is usually driving the product team crazy with questions about feature support in Silverlight.