Sunday, January 3, 2010

Silverlight and JavaScript interaction

In Silverlight business applications, we may need to pass data to the Silverlight control.  If the volume of data is not big, we can consider using Silverlight HTML Bridge to communicate between JavaScript and Silverlight. This post summarizes how to call JavaScript from Silverlight and vice versa.

Silverlight HTML Bridge is the technology that enables to call 
JavaScript from Silverlight managed code and call Silverlight managed code from JavaScript.  The following example will use some simple code to demonstrate the 2 parts and point out some usual difficulties developers may encounter.

Call Silverlight from JavaScript

In the test.aspx file, I have the following form: 
  
    <form id="form1" runat="server" style="height:100%;">
        <asp:ScriptManager ID="ScriptManager1" runat="server">                          </asp:ScriptManager>
        <div>
            <input type="button" value="Start Silverlight" onclick="startSilverlight();" />
            <input type="hidden" id="hiddenString" value="0.85,0.78,0.10,0.12,0.90" />
        </div>
        <div style="height:100%;">
            <asp:Silverlight ID="Xaml1" Visible="true" runat="server" Source="~/ClientBin/SilverlightTest.xap"                             MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
        </div>

    </form>

And I also have the following JavaScript in the same page: 
<script type="text/javascript" language="javascript">
    function startSilverlight() {
        var plugin = document.getElementById("Xaml1");
        if (plugin == null) {
            alert("xaml1 is null");
            return;
       
}
        var strControl = document.getElementById("hiddenString");
       
var str = strControl.value;
        plugin.Content.Page.StartShow(str);
    }

</script>

In Silverlight, the code-behind file contains the following code:
    [ScriptableType]
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            HtmlPage.RegisterScriptableObject("Page", this);
        } 
        [ScriptableMember]
        public void StartShow(string data)
        {
            char[] charSeparators = { ',' };
            string[] result;
            result = data.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);
            float values[] = new float[result.Length];
            int i = 0;
            foreach (var str in result)
            {
                values[i++] = float.Parse(str);
            } 
            UpdateLayout(values);
        }
    }

When users click the button on test.aspx page, the hidden text can be passed to Silverlight.

Call JavaScript from Silverlight

In test.aspx, I added
<script type="text/javascript" language="javascript">
    function getSilverlightValue(text) {
        alert(text);
    }

</script>

In Silverlight code-behind file, use HtmlPage to call the function: 
    HtmlPage.Window.Invoke("getSilverlightValue", "A test string");

Final Words

This is all the things related with how JavaScript and Silverlight interact. However, what I want to point out here is this convenient method may have some performance issues when you want to pass high volume of data to Silverlight.  In my real project, I passed over 30 Mega pure data to Silverlight and I needed to parse the data, so the data needed over 10 seconds to be fully displayed.  Some users may not want this experience.  If that's the case, you may seek help from WCF to retrieve data in an asynchronous way.