DCSIMG
Silverlight and JavaScript interoperability - it's really simple - Alex Golesh's Blog About Silverlight Development

Silverlight and JavaScript interoperability - it's really simple

I'd like to answer on one of very frequent question I've been asked by great many developers, which playing with Silverlight v1.1 Alpha.

So, how one can execute managed code from JavaScript, and how JavaScript can get notification (event) from Silverlight (and possibly lunch some JavaScript functionality)?

Well, it's pretty simple. First, lets create Silverlight project (I'm using Visual Studio 2008 with Silverlight tools for Visual Studio 2008 installed).

Well... After creating the projects, let's do some coding... First of all, let's add some HTML button to out TestPage...

<input id="Button2" type="button" value="Test JavaScript to Silverlight Interoperability" onclick="JavaScriptToSilverlightInteroperability();"/>

In button "onclick" event I define call to some JavaScript function in my example I've called it "JavaScriptToSilverlightInteroperability".

Lets write such a function definition in JavaScript part of TestPage:

function JavaScriptToSilverlightInteroperability(sender, args)
{

}

Well... So far, so good. Now let's do some basic XAML editing... I'll add some TextBlock to my default Page.xaml and will change background... Here what I've got:

<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="Silverlight_JS_Interoperability.Page;assembly=ClientBin/Silverlight_JS_Interoperability.dll"
        Width="640"
        Height="480"
        Background="LightSalmon"
        >
  <!--Some text block to enable some basic output-->
  <TextBlock x:Name="txtMyText" Canvas.Left="10" Canvas.Top="10" Width="300" Height="25"/>
</Canvas>

Now it is a time to write some real code (C#)... I'll gonna add some class, which will be accessed from JavaScript, implement couple of functions and property, define some Event and fire it. Most important here, is  that every part of managed code, which need to be accessed from JavaScript need to be decorated with [Scriptable] attribute:

 image

Now this is my very simple class:

//Class which will be acessed by Javascript
[Scriptable]
public class ManagedClass
{
    public ManagedClass()
    {
        //Registering class as "Scriptable" object to enable it being called from Javascript - will be used in Event firing from Silverlight to Javascript
        WebApplication.Current.RegisterScriptableObject("ManagedClassInstance", this);
    }

    //Event definition
    [Scriptable]
    public event EventHandler CallbackToBrowser_SomeEvent;

    //Some functions & Properties
    [Scriptable]
    public void VoidFunction(string Param1, string Param2)
    {
        //Some functionality here... For example updating textblock on XAML
        Page.txtBlock.Text = Param1 + " " + Param2;
    }

    [Scriptable]
    public int IntFunction(int Param)
    {
        //Firing event to Javascript
        CallbackToBrowser_SomeEvent(this, new MyEventAtgs() { SomeValue = "This is test message from Silverlight event!" });

        //Some functionality here....
        return Param;
    }

    [Scriptable]
    public int SomeProperty { set; get; }
}

Event arguments definition:

//Event arguments class - pretty simple here
public class MyEventAtgs : EventArgs
{
    [Scriptable]
    public string SomeValue {get; set;}
}

And finally, the main Page class:

public partial class Page : Canvas
{
    //Class being called by Javascript - instanciation
    ManagedClass managedClassExample = new ManagedClass();
    static internal TextBlock txtBlock;

    public void Page_Loaded(object o, EventArgs e)
    {
        // Required to initialize variables
        InitializeComponent();

        //Registering class as "Scriptable" object to enable it being called from Javascript
        WebApplication.Current.RegisterScriptableObject("Silverlight_Test_Class", managedClassExample);

        //simple access to XAML control to eneble class make some changes in Silverlight textblock
        txtBlock = txtMyText;
    }
}

Almost done... Pay attention, that instance of class, which I'm gonna access from JavaScript was initialized in page load event handler, and it was registered as "Scriptable object", which actually gives it access from JavaScript.

Now all I need to do, is actually access it from JavaScript and make JavaScript to "listen" to my CallbackToBrowser_SomeEvent event. Here is "JavaScriptToSilverlightInteroperability" function body:

function JavaScriptToSilverlightInteroperability(sender, args)
{
    //Receives Silverlight control from document
    var silverlightControl = document.getElementById("SilverlightControl").Content;
    
    if (silverlightControl)
    {
      //Silverlight void function call example
      silverlightControl.Silverlight_Test_Class.VoidFunction("Executed from", "HTML button click!");
      
      //Silverlight property set example
      silverlightControl.Silverlight_Test_Class.SomeProperty = 123;
      
      //Silverlight function call with returned value example      
      var IntFunction = silverlightControl.Silverlight_Test_Class.IntFunction(12345);
      alert("Got IntFunction return = " + IntFunction);
      
      //Silverlight property get examples      
      alert("SomeProperty = " + silverlightControl.Silverlight_Test_Class.SomeProperty);      
    }
}

And here is plumbing needed to "connect" managed events to BLOCKED SCRIPT

1. In function "CreateSilverlight" add event handler, which give me an opportunity to do some work:

//contains calls to silverlight.js, example below loads Page.xaml
function createSilverlight()
{
    Silverlight.createObjectEx({
        source: "Page.xaml",
        parentElement: document.getElementById("SilverlightControlHost"),
        id: "SilverlightControl",
        properties: {
            width: "100%",
            height: "100%",
            version: "1.1",
            enableHtmlAccess: "true"
        },
        events: {
            onLoad: onLoaded //Execute function on Silverlight control load
        }
    });

2. Now, lets write this "onLoaded" function  and write actual JavaScript event handler:

//Silverlight control OnLoaded event handler
function onLoaded(sender, args)
{
    sender.Content.ManagedClassInstance.CallbackToBrowser_SomeEvent = OnAlertCallback;
}

//Function to handle Silverlight events
function OnAlertCallback(sender, args)
{
    alert(args.SomeValue);
} 

That's it... We done...

Let's lunch this project and click on HTML button:

image5

 

Everything worked as planned - we got out managed code executed, updated XAML element from code, raised managed event and captured it in JavaScript.

And last, but not least, we able to debug out managed code while executing the project!!!

image9

Hope this helps :)

 Here is sources.

 

Enjoy,

Alex

Published Thursday, December 06, 2007 7:58 PM by Alex Golesh

Comments

# re: Silverlight and JavaScript interoperability - it's really simple

Hi,

Good Article and code is also very good.

But I am having problem creating the ManagedClass.

I cannot write the line

WebApplication.Current.RegisterScriptableObject("ManagedClassInstance", this);

bec' WebApplication does not come in Intellisense.

Which namespace should I add? I am using SL 3.

Tuesday, March 09, 2010 4:32 PM by S B Ray

# re: Silverlight and JavaScript interoperability - it's really simple

This article is more than 2 years old... Use App.Current.RegisterScriptableObject instead WebApplication. Also [Scriptable] changed with [ScriptableMember] and [ScriptableType].

Regards,

Alex

Tuesday, March 09, 2010 8:44 PM by Alex Golesh

# re: Silverlight and JavaScript interoperability - it's really simple

Hi Alex,

How do you access the TextBlock within Managed Class?

I have  created a ManagedClass within the SL Application but I cannot access the Textblock within the MainPage.

So Page has turned to MainPage but I don't get the x:name of the Textblock in the Intellisense.

I did like this:

public class ManagedClass:MainPage

   {

       public void VoidFunction(string Param1, string Param2)

       {

           //Some functionality here... For example updating textblock on XAML

               //Page.txtBlock.Text = Param1 + " " + Param2;

            MainPage.          

       }

  }

Thanks for your previous reply.

Wednesday, March 10, 2010 8:38 AM by S B Ray

# re: Silverlight and JavaScript interoperability - it's really simple

S B Ray:

You doing wrong. The fact, that you derive from the class still doesn't mean, that you ManagedClass will get the internal variables.

If you trying to achieve "visual inheritance" in Silverlight there are better ways to do it.

I suggest you to read tutorials :)

Regards,

Alex

Wednesday, March 10, 2010 8:56 AM by Alex Golesh

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above: