Putting a Silverlight viewer on a web page is a lot of work. You have to import the Silverlight.js file (and make sure it's deployed to the web server), create a div to contain the viewer, and write some Javascript code to call Silverlight.createObject(). To me, this is just begging for an ASP.NET control - so I whipped up one of my own.
So what do I want my control to do for me? Let's start at the top with the Silverlight.js file. I want this to be an embedded resource so that I don't always have to remember to copy it in to a new project. If you're not familiar with this technique, it's been around since .NET 2.0 - keep up! :) You just throw the Silverlight.js file into your project and set it's build action to "Embedded Resource". Here's a screenshot:
Add it to your project's AssemblyInfo.cs like this:
// Embeded Resources
[assembly: System.Web.UI.WebResource("knw.Silverlight.Silverlight.js", "application/x-javascript")]
Then my control's code tells the page where to find it like this:
Page.ClientScript.RegisterClientScriptInclude("Silverlight.js", Page.ClientScript.GetWebResourceUrl(this.GetType(), "knw.Silverlight.Silverlight.js"));
Here is a link to an article on Code Project that explains the technique in a bit more detail.
Next, I want my control to render the container div for the Silverlight viewer. This is pretty straightforward - I just override Render() and use the HtmlTextWriter that's passed in. Here's what it looks like:
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
writer.AddAttribute("id", ID + "Div");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.RenderEndTag();
}
Note I'm just concatenating "Div" onto the existing ID of my control when building the div's id, but that should make it unique.
The only thing that's left is the call to Silverlight.createObject(). There are a few variables in this call that I thought could be exposed as properties of my control. Specifically, the path to the Xaml document, the height and width of the viewer, and the background color. I'm using C# 3.0, so I took advantage of another language feature - automatic properties. Here's what that code looks like:
public string Xaml { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public Color BackgroundColor { get; set; }
Lastly, I need to build the actual javascript to create the Silverlight viewer and register it with the page to run as a startup script. Like this:
string createObjectScript = string.Format("<script>Silverlight.createObject( \"{0}\", document.getElementById( \"{1}Div\" ), \"{2}Ctrl\", {{ width:'{3}', height:'{4}', inplaceInstallPrompt:false,background:'{5}', isWindowless:'false', framerate:'24', version:'1.0' }},{{ onError:null,onLoad:null }},null );</script>", Xaml, ID, ID, Width, Height, ColorTranslator.ToHtml(BackgroundColor) );
Page.ClientScript.RegisterStartupScript( this.GetType(), ID + "Create", createObjectScript );
At first glance, that code looks pretty confusing. All it's actually doing is using string.Format() to build the call to Silverlight.createObject(). {0} is the path to the Xaml, {1} is the ID of the control + "Div" (the id of container div), {2} is the ID of the control + "Ctrl" (a unique id for the viewer itself), {3} is the width, {4} is the height, and {5} is the background color (converted from a System.Drawing.Color using the System.Drawing.ColorTranslator class). Oh yeah, and you have to escape curly braces when using string.Format() by doubling them.
Ok, that was a lot of work - what has it bought me? Well, now when I want to use Silverlight on an .aspx page, all I have to do is add a reference to my DLL, register it at the top of the .aspx page, and put the control on the .aspx page somewhere. Which looks like this:
<knw:Silverlight id="Silverlight1" runat="server" Xaml="MySilverlight.xaml" BackgroundColor="Gray" Height="200" Width="200" />
I will attach the code for both the control and an example of using it to this post. I'll be using this control in future Silverlight posts here - plus, I do intend to extend it to do more in the future (as I learn more about Silverlight). So, I'll try to post updates here from time to time. I hope it's useful to someone! :)