Geeks With Blogs
Peter Tweed Exploring and explaining the mysteries of .NET

When building RIAs there is sometimes both the need for complex rich interfaces and simpler standard html interfaces.  This is more common when introducing the rich experience into an existing web application where it makes sense to maintain some of the existing functionality and introduce the power of Silverlight in targeted functions.

In such a circumstance when we have business functionality in and in ASP.NET/HTML pages - wouldn't it be great if we had the ability to interop between both the Silverlight and JavaScript in the browser?  Silverlight provides this ability in the HTML Bridge.

In this post, we'll explore how to use managed objects in JavaScript, how to attach managed code delegates to javascript events and how to call managed code functions from JavaScript.

Usage scenarios for this post:

a.    A user will enter information about a person (name and hobby) into fields in a Silverlight application, click a button and the information will be sent to a JavaScript function that will display the values in a HTML table

b.    A user will enter numeric values in the HTML page and then click a button whose click event will be handled in the Silverlight application, which will retrieve the vales from the HTML document, sum them and display the values and the result in the Silverlight application

c.    A user will select a color from a drop down in the HTML page and the on change JavaScript event will call a managed code function on the Silverlight page in displayed in the Silverlight application with the color selected, which will change the background color of the Silverlight page

Steps:

1.    Create a new silverlight application named HTMLBridge

2.    Choose to add a test web application for the new solution

3.     Replace the LayoutRoot grid in the MainPage.xaml file with the following XAML

  <Grid x:Name="LayoutRoot" Background="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"   >

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="100"></ColumnDefinition>

            <ColumnDefinition Width="*"></ColumnDefinition>

        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

            <RowDefinition Height="30"></RowDefinition>

        </Grid.RowDefinitions>

 

        <TextBlock Text="Person Info" FontSize="20" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" ></TextBlock>

 

        <TextBlock Text="Name" Grid.Column="0" Grid.Row="1" ></TextBlock>

        <TextBlock Text="Hobby" Grid.Column="0" Grid.Row="2" ></TextBlock>

 

        <TextBox x:Name="txtName" Grid.Column="1" Grid.Row="1"></TextBox>

        <TextBox x:Name="txtHobby" Grid.Column="1" Grid.Row="2"></TextBox>

        <Button x:Name="btnSendPerson" Content="Send Person" Grid.Column="1" Grid.Row="3" Width="100" Click="btnSendPerson_Click"></Button>

 

        <TextBlock Text="Calculation" FontSize="20" Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="2" ></TextBlock>

 

        <TextBlock Text="x" Grid.Column="0" Grid.Row="5" ></TextBlock>

        <TextBlock Text="y" Grid.Column="0" Grid.Row="6" ></TextBlock>

        <TextBlock Text="result" Grid.Column="0" Grid.Row="7" ></TextBlock>

 

        <TextBlock x:Name="lblX" Grid.Column="1" Grid.Row="5"></TextBlock>

        <TextBlock x:Name="lblY" Grid.Column="1" Grid.Row="6"></TextBlock>

        <TextBlock x:Name="lblResult" Grid.Column="1" Grid.Row="7"></TextBlock>

     

    </Grid>

 

This XAML defines entry fields for name and hobby for person information and a display section for calculation results and numeric values retrieved from the HTML document.

 

4.    Add the following line at the top of the MainPage.xaml.cs file

 

using System.Windows.Browser;

 

5.    Paste the following code after the constructor in the MainPage class

 

        private void btnSendPerson_Click(object sender, RoutedEventArgs e)

        {

            PersonInfo p = new PersonInfo() { Name = txtName.Text, Hobby = txtHobby.Text };

            HtmlPage.Window.Invoke("ReceivePersonInfo", p);

        }

 

        [ScriptableMember()]

        public void ChangeColor(string color)

        {

            switch (color)

            {

                case "Red":

                    this.LayoutRoot.Background = new SolidColorBrush(Colors.Red);

                    break;

                case "Green":

                    this.LayoutRoot.Background = new SolidColorBrush(Colors.Green);

                    break;

                case "Orange":

                    this.LayoutRoot.Background = new SolidColorBrush(Colors.Orange);

                    break;

                default:

                    this.LayoutRoot.Background = new SolidColorBrush(Colors.LightGray);

                    break;

            }

        }

 

6.    Paste the following code after the MainPage class within the HTMLBridge namespace

 

 

    [ScriptableType()]

    public class PersonInfo

    {

        public string Name { get; set; }

        public string Hobby {get; set; }

    }

 

 

At the bottom of this section of code is the PersonInfo class.  This is the managed type object that will be passed to a JavaScript function, which will display the Name and Hobby entered in the Silverlight application.  Please note the ScriptableType attribute which says that all public properties and methods on the class will be accessible by JavaScript.

 

At the top of this code is the click event handler for the button in the XAML.  When the user clicks it a new PersonInfo object is created with the information entered via the UI. Then the JavaScript function “ReceivePersonInfo” is called with the PersonInfo object as a parameter.  This is all we need to do to pass a managed object to JavaScript.

 

After the button click event handler is the function ChangeColor that accepts a string and based on its value changes the background color of the page.  Note that the function is decorated with the ScriptableMember attribute.  This makes this function available for JavaScript to call for this class.

 

7.    Add the following line at the top of the App.xaml.cs file

 

using System.Windows.Browser;

 

8.    Replace the code in the Application_Startup event handler with the following

 

            MainPage page = new MainPage();

 

            this.RootVisual = page;

 

            HtmlDocument doc = HtmlPage.Document;

 

            doc.GetElementById("btnSendCalculation").AttachEvent("click", new EventHandler((o, args) =>

            {

                double x = double.Parse(doc.GetElementById("txtX").GetAttribute("value"));

                double y = double.Parse(doc.GetElementById("txtY").GetAttribute("value"));

                double result = x + y;

 

                page.lblX.Text = x.ToString();

                page.lblY.Text = y.ToString();

                page.lblResult.Text = result.ToString();

 

            }));

 

            HtmlPage.RegisterScriptableObject("mainPage", page);

 

This code instantiates a MainPage object as the RootVisual of the application.  Next a reference to the Document object of the HTML page the Silverlight application is hosted in is retrieved.  The btnSendCalculation HTML button in the HTML document is referenced and an anonymous delegate is attached to the JavaScript click event of the button.  In the delegate the calculation x and y values are retrieved from the HTML document, added together and displayed along with the sum result in the MainPage page object.

Finally the MainPage page object is registered as a Scriptable Object so that JavaScript can directly call the ChangeColor function in the page object.

 

9.    Copy the following JavaScript functions within the script section in the head section in the HTMLBridgeTetPage.aspx file

 

        function ReceivePersonInfo(personInfo) {

            document.getElementById("spName").innerText = personInfo.Name;

            document.getElementById("spHobby").innerText = personInfo.Hobby;

        }

 

        var SLControl = null;

        function pluginLoaded(sender, args) {

            SLControl = sender.getHost();

        }

 

        function ColorChanged() {

            var colorSelIdx = document.getElementById("colorSelection").selectedIndex;

            var color = document.getElementById("colorSelection").options[colorSelIdx].text;

 

            SLControl.Content.mainPage.ChangeColor(color);

        }

 

The ReceivePersonInfo function is the one that is called on the button click event handler in the Silverlight MainPage class and displays the PersonInfo object members in the HTML page.

The pluginLoaded function will be called when the Silverlight object is loaded in the browser.  It simply gets a reference to the Silverlight object in the document.  This is then used in the ColorChanged JavaScript function to call the ChangeColor scriptable member function on the MainPage scriptable object.

 

10.  Replace the div with the id silverlightControlHost in the HTMLBridgeTestPage.aspx file with the following

 

        <div id="silverlightControlHost" style="float:left;">

        <fieldset style="width:200px; height:300px;">

        <legend >Silverlight Control</legend>

           

            <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="280">

                  <param name="source" value="ClientBin/HTMLBridge.xap"/>

                  <param name="onError" value="onSilverlightError" />

                  <param name="background" value="white" />

                  <param name="minRuntimeVersion" value="3.0.40624.0" />

                  <param name="autoUpgrade" value="true" />

                  <param name="onLoad" value="pluginLoaded" />

                  <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">

                        <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>

                  </a>

              </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>

        </fieldset>

          </div>

 

The key point to note here is the addition of the param object for the onLoad event that supplies the name of the pluginLoaded function to be called on the load of the plugin.

 

11. Add the following HTML after the above div

 

          <div style="float:right">

         <fieldset style="width:207px; height:300px;">

        <legend >HTML Controls</legend>

            <table style="background-color:Silver; height:280px;">

                <tr>

                    <td colspan="2" style="font-size:20px;"> Person Information</td>

                </tr>

                <tr>

                    <td >Name</td>

                    <td ><span id="spName"></span></td>

                </tr>

                <tr>

                    <td >Hobby</td>

                    <td ><span id="spHobby"></span></td>

                </tr>

                <tr>

                    <td >Color</td>

                    <td >

                        <select id="colorSelection" onchange="ColorChanged();">

                            <option selected="selected">[Select One]</option>

                            <option>Red</option>

                            <option>Green</option>

                            <option>Orange</option>

                        </select>

                        <input type="hidden" id="selectedColor" />

                    </td>

                </tr>

                <tr>

                    <td colspan="2" style="font-size:20px;">Calculation</td>

                </tr>

                <tr>

                    <td >x</td>

                    <td ><input type="text" id="txtX" /></td>

                </tr>

                <tr>

                    <td >y</td>

                    <td ><input type="text" id="txtY" /></td>

                </tr>

                <tr>

                    <td >&nbsp;</td>

                    <td ><input type="button" id="btnSendCalculation" value="Send Calculation" /></td>

                </tr>

            </table>

        </fieldset>

          </div>

 

This HTML defines the controls to enter the calculation  x and y values and select a color to change the background of the Silverlight control to.  The HTML controls to display the PersonInfo object received from the Silverlight control are also defined.

 

12. Run the application

 

 

13. Enter a name and a hobby for the person info in the Silverlight Control and click on the Send Person button.  The person info will be displayed in the Person Information section in the HTML Controls on the right.

 

 

14. Select a color from the Color drop down in the HTML Controls section and watch as the background of the Silverlight control changes to the selected color

 

 

15. Enter x and y values and click on the Send Calculation button and the values will be displayed with the summed result in the Silverlight control

 

 

Congratulations!!!! You have implemented interoperation between Silverlight and JavaScript and vice versa.

 

What have we done?

 

We have enabled the exposing of managed objects and their methods for consumption in JavaScript in the web page the Silverlight control is hosted in.

 

We have attached a managed code delegate to the JavaScript event of a HTML button.

 

We have called a managed code function in a scriptable object from JavaScript in the web page the Silverlight control is hosted in.

 

Conclusion

Silverlight enables the interoperation of Silverlight and JavaScript at both the type, property, method and event levels.  This allows the developer to truly integrate Silverlight with standard web technologies in the delivery of full featured thin client applications.

 

 

Posted on Saturday, August 8, 2009 12:38 AM ASP.NET , Silverlight | Back to top


Comments on this post: HTML Bridge - Silverlight JavaScript Interop

# re: HTML Bridge - Silverlight JavaScript Interop
Requesting Gravatar...
Interesting,

Silverlight enables the interoperation of Silverlight and JavaScript at both the type, property, method and event levels. And that is excelent for deveopers to use it

Thanks for writing, most people don't bother.
Left by web development company on Aug 27, 2009 10:06 AM

# re: HTML Bridge - Silverlight JavaScript Interop
Requesting Gravatar...
You're very welcome. SL has so much to offer building great RIAs and this is one area that is important in offering truly interactive and modularized applications that can be mashed together in the usual "mashup" way.
Left by Peter on Sep 13, 2009 10:36 AM

# re: HTML Bridge - Silverlight JavaScript Interop
Requesting Gravatar...
I am converting a WPF user control to silverlight and at the same time transitioning from java to .Net. Still trying to figure out the anatomy of a silverlight application but that will come eventually. Excellent tuorial ... Thanks! Note: this does not work in Firefox 3.6.13
Left by Keith on Jan 12, 2011 8:56 AM

# re: HTML Bridge - Silverlight JavaScript Interop
Requesting Gravatar...
Thank you very much! a very useful tutorial.
Left by Meenakshi on May 16, 2011 1:39 AM

# re: HTML Bridge - Silverlight JavaScript Interop
Requesting Gravatar...
you are genius man!!..thanks for nice article and code base.
Left by Bhavesh on Aug 16, 2012 1:04 PM

Your comment:
 (will show your gravatar)


Copyright © PeterTweed | Powered by: GeeksWithBlogs.net