Calling Silverlight managed code (C#) from the client-side (Javascript)
Even though we write managed code to build Silverlight apps, it all exists on the client side, so we need to be able to have html and Silverlight interact without hitting the server-side. This is built into Silverlight 2, and is very similar to exposing C# web service calls to the client using ASP.net AJAX... only we never have to make calls to the server.To provide a quick example, I'll create a simple Silverlight object that contains only a TextBox and show how it can be updated from Javascript. I'll create an html text box that updates my silverlight object's TextBox while I type. So in my html test page, I'll add an <input/> right above the generated code for the Silverlight object. Before I write client side functionality, I want to setup my Silverlight code to accept commands from Javascript. First, the Xaml:
<UserControl x:Class="JStoManagedCode.Page" xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock x:Name="SilverlightText"></TextBlock>
</Grid>
</UserControl>
Next, in my code behind for the root visual (Page.xaml.cs), I’ll need to:
a) Make the class a scriptable type, and register it in the html page
b) Create a function to update the Silverlight text, and expose it to the client.
To make the class scriptable, I need to add a [ScriptableType] attribute to the class declaration (System.Windows.Browser namespace). Then I’ll register the class to the client by calling HtmlPage.RegisterScriptableObject. Then I’ll write a function that updates the Silverlight object, and will add a [ScriptableMember] attribute to that function. Here’s what the final code looks like:
using System.Windows.Controls;
using System.Windows.Browser;
namespace JStoManagedCode
{
[ScriptableType]
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
HtmlPage.RegisterScriptableObject("SilverlightTextSample", this);
}
[ScriptableMember]
public void UpdateSilverlightText(string newText)
{
SilverlightText.Text = newText;
}
}
}
Now my Silverlight object is ready to accept calls to UpdateSilverlightText via Javascript! Let’s call it.In my Html page, I’ll add a textbox (input) above the silverlight object add an event handler to the textbox’s onkeypress event:
<input id="clientTextBox" onkeypress="clientTextChanged(event)" />
<!-- Runtime errors from Silverlight will be displayed here.
This will contain debugging information and should be removed or hidden when debugging is completed -->
<div id='errorLocation' style="font-size: small;color: Gray;"></div>
<div id="silverlightControlHost">
<object id="silverlightObject" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/JStoManagedCode.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="white" />
<a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
</a>
</object>
<iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
</div>
Finally I’ll write the Javascript event handler that in turn calls my Silverlight function:
function clientTextChanged ( e ) {
var newText = document.getElementById("clientTextBox").value;
var silverlightObject = document.getElementById("silverlightObject");
var keynum; if ( window.event ) { // IE
keynum = e.keyCode;
}
else if ( e.which ) { // Other browsers
keynum = e.which;
}
newText += String.fromCharCode(keynum);
silverlightObject.content.SilverlightTextSample.UpdateSilverlightText(newText);
}
And here’s how it all looks (aplogies for the screenshot, I'm unable to post Xap files):
