Silverlight as a better JavaScript

This article was originally published in VSJ, which is now part of Developer Fusion.
The first two parts of this mini-series on Silverlight (see the September and October issues of VSJ) focused on providing a general overview of the Silverlight architecture, and delved into how you host a Silverlight application within the browser. All the interactivity within the application was shown using event handlers written in JavaScript.

Well, version 1.0 of Silverlight is now released amid much fanfare, and is heavily in use on sites such as ET Online’s Emmy Awards homage and the Halo 3 game guide. The common factor on these sites is the way that Silverlight is being used to provide a rich user experience with cool animations and neat video features, all bundled into a small plug-in package. So at this point it’s certainly tempting to pigeon-hole Silverlight as being a budget media-player application, but there’s actually a whole lot more to it than that. And to prove just how much more there is, in this article we’re going to look at one of the more niche uses of Silverlight as a “better” JavaScript. The Calculator Figure 1 shows a simple, browser-based calculator. There are no videos playing on the buttons, nor are there any funky animations: it’s just a simple, postfix notation calculator that can perform basic arithmetic functions.

Figure 1
Figure 1: The Silverlight Calculator

Clearly, if you were tasked to write a calculator like this for the browser, you would expect to handle all of the interaction on the client-side using JavaScript: there’s certainly no need for AJAX or ASP.NET UpdatePanels, and definitely no need for a full page round-trip cycle. But what if you’re actually not that good with script, and certainly have minimal exposure to the subtle nuances of how script works on different browsers? You could rush out and buy a good book on JavaScript programming, but you might already be a skilled Visual Basic or C# developer. Is there a way of leveraging those skills on the browser client? There certainly is: it’s called Silverlight 1.1.

Silverlight 1.1

Silverlight 1.1 offers you an interesting alternative to writing JavaScript, at least for some of the most common browsers. Unlike its 1.0 predecessor, the Silverlight 1.1 plug-in supports a CLR – yes, full managed code – on the Mac OS X and Windows platforms, assuming that you’re running Safari, FireFox or Internet Explorer. In the coming months you will also see support on Linux, so you’re pretty well covered for the vast majority of users.

Of course, Silverlight 1.1 supports all the fancy media-centric, animation and other funky XAML-based features of the earlier release, but I won’t be focusing on them in this article.

agclr, mscorlib and friends

Once you’ve headed over to the Silverlight site, followed the links and installed the Silverlight SDK, you’ll find that you have a new CLR installed on your computer. Don’t bother looking for it in the traditional %WINDIR%/Microsoft.NET folder, because you won’t find it there. Instead, open up the folder where you installed the SDK (in my case C:\Program Files\Microsoft Silverlight) and you will find a collection of assemblies such as mscorlib.dll, agclr.cll, system.dll and system.silverlight.dll. This collection of assemblies represents the cut down, but highly functional CLR and .NET Framework Class Library that you can use within your Silverlight application. With full support for C#, Visual Basic and even with new dynamic language support, you’re going to feel completely at home writing the same style of code that you would previously have written for Windows Forms, server-side ASP.NET or WPF.

The Framework Class Library that is provided with Silverlight is somewhat limited in scope, but with support for generic collections, I/O, threading and Web Service requests, it is still highly capable. Currently, one of the best ways of seeing precisely what’s available is to use Lutz Roeder’s now famous Reflector. This will provide you complete insight into the full range of supported features in the library, although you must bear in mind that this is only an alpha release and is thus subject to considerable change.

Security and the Silverlight sandbox

It’s certainly great having all of this code available for use on the client, but how does it impact upon security? Silverlight runs inside a very stringent sand-box that will, for example, prohibit I/O access other than through Isolated Storage unless authorised by the user via the common file dialogs.

The Calculator.aspx page

Let’s start off by looking at the mark-up for the Calculator page, Calculator.aspx, which is shown in Figure 1.
<%@ Page Language=”C#”
	AutoEventWireup=”true”
	CodeFile=”Calculator.aspx.cs”
	Inherits=”CalculatorPage” %>

<!DOCTYPE html … >
<html
xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title>Silverlight Calculator</title>
<style type=”text/css”>
	input[type=button]
	{
	}
	input[type=text]
	{
	}
</style>
<script type=”text/javascript”
	src=”Silverlight.js”></script>
<script type=”text/javascript”
	src=”Default.aspx.js”></script>
</head>
<body>
	<form id=”form1” runat=”server”>
	<div … >
		<table border=”0”
			cellpadding=”0”
			cellspacing=”0”>
		<tr>
		<td colspan=”3”>
		<input type=”text”
			id=”txtValue”
			style=”width: 150pt;“
			readonly=”readonly” /></td>
		<td>
		<input type=”button”
			id=”btnReset”
			value=”CE” /></td>
		</tr>
		<tr>
		<td>
		<input type=”button” id=”btn7”
			value=”7” /></td>
		<td>
		<input type=”button” id=”btn8”
			value=”8” /></td>
		<td>
		<input type=”button” id=”btn9”
			value=”9” /></td>
		<td>
		<input type=”button”
			id=”btnAdd”
			value=”+” /></td>
		</tr>
		<!--
		Other rows of buttons elided
		-->
		…
	</form>
	<div id=”SilverlightControlHost”>
		<script type=”text/javascript”>
			createSilverlight();
		</script>
	</div>
</body>
</html>
The main things to note here, other than the expedient but ugly use of a <table> for the layout, are as follows:
  1. I’m using standard client-side HTML controls for the UI. This was by design for this article, in order to reinforce the fact that the managed code executed by the Silverlight CLR is operating on the client. You can equally well use ASP.NET server-side controls so that you can program against them using managed code on both the client and the server.
  2. The highlighted script files, and the <div> with the SilverlightControHost id, are essential to enabling Silverlight. As discussed in the previous articles, this is how the Silverlight plug-in creates your Silverlight content on the page. Even though we’re not going to be providing a user interface in Silverlight, we still need these items in order to pull down and execute the code.

Enabling HTML interactivity

The purpose of this article is to demonstrate how managed code can interact with the HTML elements on the page. To achieve this, you obviously have to identify the elements, which I’ve done in this case by specifying their id attribute. However, you also need to make sure that your Silverlight code is allowed access to them. This involves setting some parameters within the createSilverlight() method that is found in the Calculator.aspx.js file:
function createSilverlight()
{
	Silverlight.createObjectEx({
		source: “CalcPage.xaml”,
		parentElement:
		document.getElementById(
		“SilverlightControlHost”),
		id: “SilverlightControl”,
		properties: {
			width: “0”,
			height: “0”,
			version: “1.1”,
			enableHtmlAccess: “true”,
			isWindowless: “true”
		},
		events: {}
	});
}
The naming pattern of Calculator.aspx.js is just a convenience used for identifying the JavaScript file for a page; this code is not compiled or executed on the server. You will see that the enableHtmlAccess parameter has been set to “true”. And yes, that really is true inside quotes. Unless you set enableHtmlAccess to “true”, any attempt to interact with HTML elements on the page will yield the dialog seen in Figure 2.

Figure 2
Figure 2: Errors happen unless enableHtmlAccess is set to “true”

There are a couple of other parameters of interest. isWindowless is also set to “true” because we desire no window at all, allowing HTML elements to lie atop the Silverlight control. This is not necessarily important for the calculator, as you might also have noticed that its height and width are both set to “0”. However, if you’re writing a page that has HTML overlaid onto the same UI space as your Silverlight content, this needs to be set. Finally, you’ll have seen the source parameter that specifies a XAML file, CalcPage.xaml. As was discussed in the previous articles, XAML is typically used to describe the user interface of a Silverlight application. However, the user interface for the calculator is written in pure HTML, so why do I need a XAML file? Let’s find out.

Hooking the Loaded event

The answer is that the XAML will be used to generate half of a class that will then be instantiated in the Silverlight control, in order to provide the root element. This will typically be a Canvas onto which we’d create a UI, but in this case it’s sneakily set to be invisible and occupy no width and height. What’s great about this Canvas, though, it that it provides us with a hook – the Loaded event – that we can use to connect up event handlers for the client-side controls. Here’s the content of CalcPage.xaml:
<Canvas x:Name=”parentCanvas”
xmlns=”http://schemas.microsoft.com/
	client/2007”
xmlns:x=”http://schemas.microsoft.com/
	winfx/2006/xaml”
	Loaded=”Page_Loaded”
x:Class=
”CalcLibrary.CalcPage;
	assembly=
	ClientBin/
	CalcLibrary.dll”
	Width=”0”
	Height=”0”
	Background=”White”
	Visibility=
	”Collapsed”
>
</Canvas>
This also highlights one other interesting aspect of working with Silverlight 1.1: how does it know where to download the code for the application from? As you can see from the x:Class attribute, it’s expecting the code for the class to be placed in an assembly called CalcLibrary.dll, which is stored within a ClientBin folder. It’s time to see where these come from.

Silverlight class libraries

I used Microsoft Visual Studio 2008 Beta 2, with the Microsoft Silverlight 1.1 alpha (September Refresh), to build the Silverlight Calculator, and I would recommend that this as the platform of choice over Microsoft Visual Studio 2005 if you’re working with Silverlight 1.1.

The solution consists of two projects: a completely bog standard ASP.NET Web Site, and a Silverlight Class Library, as shown in Figure 3.

Figure 3
Figure 3: The complete SilverCalc solution

Undoubtedly, the easiest way to build a Silverlight 1.1 application, especially when integrating them into existing Web sites, is to use a Silverlight Class Library project. Visual Studio 2008 enables you to link them into the Web site simply by right clicking on the site’s folder in Solution Explorer and selecting Add Silverlight Link… from the resulting menu, as shown in Figure 4.

Figure 4
Figure 4: Adding a link to a Silverlight project

When you add the link, Visual Studio 2008 will create the ClientBin folder for you and copy the built Silverlight Class Library into it. It will also copy any XAML files across into the Web Site so that they can be downloaded as needed. The important thing to remember with this is that you should never edit the XAML files that have been copied to the Web Site, because they are re-copied across after each build; always work on the file in the Silverlight Class Library project.

Client-side C#

It’s finally time to get down and dirty with the code for the calculator. First up we have the simple calculator implementation class:
namespace CalcLibrary
{
	public class Calc
	{
		public double CurrentValue {
			get; set; }
		public void Add(double val)
				{ CurrentValue += val; }
		public void Subtract(
			double val)
			{ CurrentValue -= val; }
		public void Divide(double val)
			{ CurrentValue /= val; }
		public void Multiply(
			double val)
			{ CurrentValue *= val; }
		public void Reset()
			{ CurrentValue = 0.0d; }
	}
}
As you can see, the Calc type simply maintains a current value and allows you to perform a number of arithmetic operations on that value. It is, however, written in C#, utilising features such as the new C# 3.0 simplified property mechanism. I am confident that you will let your imagination run riot with the possibilities of more advanced code than this.

The real fun comes with the code behind the CalcPage.xaml file, selected highlights of which are shown in the following C# code which bridges to HTML elements:

namespace CalcLibrary
{
	public partial class CalcPage :
		Canvas
	{
		Calc theCalculator =
			new Calc();
		// Flag to indicate that an
		// operation button was the
		// last button clicked
		bool cmdClicked = true;
		public void Page_Loaded(
			object o, EventArgs e)
		{
			// Required to initialize
			// variables
			InitializeComponent();
		SetupOperationEventHandlers();
			SetupDigitEventHandlers();
		}
		private void
	SetupOperationEventHandlers()
		{
			AttachClickEvent(
				“btnAdd”, Add );
			// Add event handlers for
			// other operation buttons
			…
		}
		void AttachClickEvent(
			string control,
			EventHandler<HtmlEventArgs>
			target )
		{
			HtmlDocument document =
				HtmlPage.Document;
			HtmlElement elem =
				document.GetElementByID(
				control);
			elem.AttachEvent(
				“onclick”, target );
		}
		void Add( object sender,
			HtmlEventArgs e )
		{
			cmdClicked = true;
			theCalculator.Add(
				GetValue() );
			SetTextValue(
	theCalculator.CurrentValue );
		}
		// Methods for Set, Subtract,
		// Divide, Multiply not shown
		// for brevity
		double GetValue()
		{
			HtmlDocument doc =
				HtmlPage.Document;
			HtmlElement txt =
				doc.GetElementByID(
				“txtValue”);
			string val =
			txt.GetAttribute( “value” );
			if( val == null ) val = “”;
			return Double.Parse( val );
		}
		private void SetTextValue(
			double value )
		{
			HtmlDocument doc =
				HtmlPage.Document;
			HtmlElement txt =
				doc.GetElementByID(
				“txtValue”);
			txt.SetAttribute( “value”,
				value != 0.0 ?
				value.ToString() : “” );
			txt.SetStyleAttribute(
				“color”, value < 0.0 ?
				“#880000” : “#000000” );
		}
		private void
			SetupDigitEventHandlers()
		{
			// attaches an onclick
			// handler for each digit
			// button
		}
		void DigitPressed( object
			sender, HtmlEventArgs e )
		{
			// manipulates the value of
			// the txtValue control
			// when a digit button is
			// clicked
		}
	}
}
As you can see from the highlighted sections, there are really only a few important steps to follow in order to program against an HTML element using C#, namely:
  1. The key bridging link between our managed Silverlight code and the HTML elements on the page is provided by the System.Windows.Browser.HtmlPage type, which exposes the current document through its static Document property. Using this is always the start point for hooking into the DOM.
  2. From the System.Windows.Browser.HtmlDocument object that is returned from step 1, you can locate any HTML element using the GetElementById() method. This model should be very familiar for existing JavaScript developers, and isn’t a million miles away from server-side ASP.NET techniques such as FindControl(). GetElementByID() will return an HtmlElement object reference which you can use to manipulate the object.
  3. To read the value of an attribute on the HtmlElement object, simply call its GetAttribute() method, specifying the attribute’s name. This will return you a string that you can parse into the appropriate CLR type.
  4. To set the value of an attribute on the HtmlElement object, call its SetAttribute() method, this time passing in the name of the attribute and the value that you would like it to be set to. Note that if you want to adjust the element’s style, use SetStyleAttribute, which takes the name of the CSS style property that you want to configure.
  5. Hooking up event handlers is done using the AttachEvent() method. This takes the name of the client side event, and a delegate of type EventHandler or EventHandler<HtmlEventArgs>. I’d always recommend the second approach, as the HtmlEventArgs parameter that you then receive is full of useful properties which can make programming the event handler much easier.
In this example, all of the HTML input button onclick events are connected in the Page_Loaded method, which you will remember is called in response to the Loaded event being raised as the content is loaded into the Silverlight control. I added the AttachClickEvent() helper method to the CalcPage class simply because all the events that are being handled by C# code happen to be button onclick events.

You can, of course, disconnect event handlers using the DetachEvent() method.

Clearly, the above code is showing you that you need to have a basic understanding of the HTML elements and what they offer, but with the power of an IntelliSense-enabled IDE behind you, this is not too onerous.

What is so impressive, though, about the way Silverlight works is that all of the client interactivity code is written in managed C#. Thus I have no worries about how events bubble in the browser, or how to write classes in JavaScript. This is powerful medicine!

Other useful features

There are many other aspects of Silverlight that make developing for, and working with, the browser easier. The System.Windows.Browser namespace is full of useful types to help with your code’s integration into the page. For example, the BrowserInformation class provides, as its name suggests, information about the user agent, whether cookies are supported and so on. The HttpUtility class is also useful if you need to encode or decode data for use in Urls.

And if you’re like me, it’s unlikely that your code is going to be perfect first time. Fortunately, Visual Studio 2008 offers full debug support for your Silverlight code, so you can set breakpoints and use the familiar Diagnostics mechanisms that you are used to when tracking down bugs. Note that engaging managed debugging in Visual Studio 2008 will disable script debugging, but the good news is that as you’re now using managed code anyway, who cares?

Conclusion

Silverlight 1.1 is not just about pretty, XAML-based user interfaces. Sure, it’s highly likely that the majority of Silverlight 1.1 applications will utilise those features, but it is not exclusively about rich media content. It affords you the opportunity to interact with HTML elements – in fact any scriptable object – using managed code. You might therefore feel that this is an easier (and richer) path to, dare I say it, the next generation of AJAX-enabled applications, with C# or Visual Basic replacing JavaScript.

There’s also no denying that Silverlight offers a deeper programming library, and one that is more familiar to many .NET developers, than that offered by JavaScript. Visual Studio 2008 in turn provides a very capable development and debugging environment that is hard to match in the scripting world. Of course, this comes at a cost. Silverlight requires a plug-in and it doesn’t have quite the reach of a pure JavaScript solution.

Somewhat cheekily, this article was entitled “Silverlight as a better JavaScript”. Ultimately, using Silverlight with managed code on the client is not going to replace JavaScript completely. Even without the fancy visuals, though, Silverlight is a powerful client-side technology that complements existing Web coding techniques superbly. And at the end of the day, you just have to love the fact that you can use your familiar .NET types, with your favourite .NET language, to write your next generation Web 3.0 applications. Now that’s cool.


Dave Wheeler is a freelance consultant and software author, working primarily with Microsoft .NET. He delivers training courses with DevelopMentor, helps moderate various Microsoft forums, and is a regular speaker at DevWeek and other conferences (he is presenting a number of talks at DevWeek 2008 in March). He can be contacted at [email protected].


Disclaimer

To get your hands on Silverlight 1.1 you need to head over to the Silverlight site and then follow the links to get the correct runtime version/SDK for your operating system.

What you’ll notice is that version 1.1 is currently only an alpha “release”. Consequently, it might be liable to a significant amount of change prior to release, so there’s no guarantee that everything you’ve seen will work with the next drop of the software.

You might also like...

Comments

About the author

Dave Wheeler United Kingdom

Dave Wheeler is a freelance instructor and consultant who specialises in .NET application development. He’s a moderator on Microsoft’s ASP.NET and Silverlight forums and is a regular speaker at ...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” - Rick Osborne