Control Interop, Silverlight-Style

A number of people have asked me in recent weeks whether two Silverlight 2 controls hosted in the same page can communicate with each other, and if so, how. I tell them they need to build a JavaScript bridge between the controls and then the controls can talk to each other just fine.

Tonight I built a sample app to demonstrate. Here’s what it looks like:

Control Interop Demo 

You drag the red ball in the upper rectangle and the blue rectangle in the lower rectangle mirrors the red ball’s moves. The interesting aspect of this application is that each rectangle represents a different Silverlight control instance. In other words, the page hosts two Silverlight controls, and the red ball lives in one control while the blue ball lives in the other.

Here are the OBJECT tags used to instantiate two Silverlight controls:

<div id=”silverlightControlHost1″>

  <object data=”data:application/x-silverlight,”

    type=”application/x-silverlight-2-b1″ width=”400″

    height=”300″ id=”SourceControl”>

    <param name=”source” value=”ClientBin/InteropDemo.xap”/>

    <param name=”onerror” value=”onSilverlightError” />

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

  </object>

</div>

   

<div id=”SilverlightControlHost2″>

  <object data=”data:application/x-silverlight,”

    type=”application/x-silverlight-2-b1″ width=”400″

    height=”300″ id=”TargetControl”>

    <param name=”source” value=”ClientBin/OtherControl.xap”/>

    <param name=”onerror” value=”onSilverlightError” />

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

  </object>

</div>

Each control has its own DIV, and each loads a different XAP file. How did I get Visual Studio to build two XAP files, each containing a separate control assembly? I just added a second Silverlight Application project to the solution. If you already have a Web project in the solution, Visual Studio asks if you want the new project linked to the existing Web project:

Add Project Dialog

Visual Studio obligingly adds the Silverlight project to the solution and configures the build settings so that building the project creates a second XAP file that, like the XAP file from the first project, is copied into the Web site’s ClientBin directory.

To link the two Silverlight controls together, I began by converting the code-behind class for the second control (the one containing the blue ball) into a scriptable class and adding a scriptable method named MoveBall:

[ScriptableType]

public partial class Page : UserControl

{

    public Page()

    {

        InitializeComponent();

        HtmlPage.RegisterScriptableObject(“other”, this);

    }

 

    [ScriptableMember]

    public void MoveBall(double x, double y)

    {

        Ball.SetValue(Canvas.LeftProperty, x);

        Ball.SetValue(Canvas.TopProperty, y);

    }

}

Then I added the following JavaScript function (the “bridge”) to the HTML page:

var _target = null;

   

function moveBall(x, y)

{

    if (_target == null)

        _target = document.getElementById(‘TargetControl’);

    _target.content.other.MoveBall(x, y);           

}

Finally, I added the following statement to the MouseMove handler in the first control (the one with the red ball):

HtmlPage.Window.Invoke(“moveBall”, x, y);

The X and Y coordinates passed in represent the current position of the red ball–the position I just moved it to in response to the latest mouse move.

See how it works? You move the red ball. The MouseMove handler that moves the ball also calls the JavaScript moveBall function, which in turn calls the second control’s MoveBall method. The red ball moves and the blue ball moves, too. This sample takes advantage of Silverlight 2’s rich DOM integration features which allow C# methods to call JavaScript functions, JavaScript functions to call C# methods, and a whole lot more.

I’ll post the source code this weekend. For now, it has been a long week, it’s late, and I’ll be locked away in a hotel all weekend building slides for my Silverlight precon at TechEd and taking care of other jobs that have piled up in my to-do list. Time to get some sleep.

UPDATE: The source code has been posted and you can download it here. In addition, I posted a new version of SilverLife that uses DispatcherTimer rather a Storyboard to drive cell animations. You can download the new version here.

Stay Informed

Sign up for the latest blogs, events, and insights.

We deliver solutions that accelerate the value of Azure.
Ready to experience the full power of Microsoft Azure?

Atmosera is thrilled to announce that we have been named GitHub AI Partner of the Year.

X