Published Friday, March 28, 2008 9:06 AM by mtaulty

Silverlight 2 - Passing Data Across Plug-In Instances

Again, this falls into the category of "just for fun" but it's something that I wanted to experiment with.

I wanted to see how easy it was to put together something that passed data from one Silverlight plug-in instance on a page to another instance (on the same page).

Silverlight applications are running in separate application domains even if they're on the same HTML page so you can't really use anything other than the HTML DOM itself or perhaps a back-end service to communicate between them.

I went with the DOM route.

I created a Silverlight class library project as I figure I'd want to reference the code I write from a number of Silverlight applications that want to talk to each other.

I guessed that if I register a scriptable object with a "well known" name from each of my Silverlight applications then they'll be able to talk to each other by invoking a method on the instance of that object that they each register.

As far as I know, I have to have an instantiatable class in order to register a scriptable object (i.e. AFAIK you can't register methods from a static class) and so I created this;

  [ScriptableType]
  public class Bridge
  {
    public Bridge()
    {
    }
    [ScriptableMember]
    public void FireReceived(string typename, string message)
    {
      SilverlightBridge.FireReceived(typename, message);
    }
  }

Also, I think the class has to be public and that's why I made it public, otherwise I'd have kept it internal to my assembly.

So...the idea is that when a message needs to travel from one Silverlight control to another we'll just find the destination control and use Javascript to get the registered script object and invoke its FireReceived method with the .NET typename and the message itself passed as a string.

Why do we need the .NET typename here as a parameter? It's because I'm using the DataContractSerializer and it wants to know typenames when you create it so it sort of bubbles up from there.

As you can see, the FireReceived method just calls a static method on a second class which is listed below;

  public static class SilverlightBridge
  {
    public static void Startup()
    {
      HtmlPage.RegisterScriptableObject(registrationName,
        new Bridge());
    }
    public static void Shutdown()
    {
      HtmlPage.UnregisterScriptableObject(registrationName);
    }
    internal static void FireReceived(string typename, string message)
    {
      if (MessageReceived != null)
      {
        DataContractSerializer ser = new DataContractSerializer(Type.GetType(typename));
        MemoryStream ms = new MemoryStream(Convert.FromBase64String(message));
        object o = ser.ReadObject(ms);

        MessageReceived(null, new MessageEventArgs()
        {
          DataObject = o
        });
      }
    }
    public static void SendMessage<T>(string controlId, T message)
    {
      DataContractSerializer ser = new DataContractSerializer(typeof(T));
      MemoryStream ms = new MemoryStream();
      ser.WriteObject(ms, message);
      string base64 = Convert.ToBase64String(ms.ToArray());

      FireReceivedOnRecipientControl(controlId, typeof(T).AssemblyQualifiedName, base64);
    }
    private static void FireReceivedOnRecipientControl(string controlId, 
      string typename, string message)
    {
      HtmlElement element = HtmlPage.Document.GetElementById(controlId);

      if (element != null)
      {
        string script = string.Format(
          "document.getElementById(\"{0}\").content.{1}.FireReceived(\"{2}\", \"{3}\");",
          controlId, registrationName, typename, message);

        HtmlPage.Window.Eval(script);
      }
    }
    public static event EventHandler<MessageEventArgs> MessageReceived;
    private static string registrationName = "silverlightBridge";
  }

With the missing class being;

  [ScriptableType]
  public class MessageEventArgs : EventArgs
  {
    [ScriptableMember]
    public object DataObject { get; set; }
  }

So, the idea here is that at Startup time in my application I call SilverlightBridge.Initialise().

Then, when I've got something to send to another Silverlight control I can call;

SilverlightBridge.SendMessage<T>("controlId", data);

and, as long as the T in question can be serialized using the DataContractSerializer and the same type is available in the receiving application then we should be able to call across ( via Javascript ) and call into the receiving Silverlight application and fire the message in there.

The receiving application can sync up to the MessageReceived event where it'll get notified and it should have a T instance delivered to it which it can then cast and carry on doing whatever it wants to do.

Note - I've done this using shared types but it'd be equally possible to deserialize using different types as long as they serialized the same way but the way I pass around typename above is not in line with going down that route.

I wrote a quick app just to test this out where you can drag a circle around in one Silverlight application and it should tell another Silverlight application where the circle is so that it can "follow along";

image

I've uploaded all of the project files here. As I say, "just for fun" this one :-)


Filed Under:

# Link Listing - March 28, 2008 @ Saturday, March 29, 2008 7:50 AM

WPF  Live Messenger - Login Screen UI [Via: Jose Fajardo ] ItemsControl: 'R' is for Rob has a Customer...

Christopher Steen

# Silverlight Cream for March 30, 2008 -- #240 @ Sunday, March 30, 2008 8:51 AM

Dan Wahlin&amp;#39;s latest articles, Cheryl at Silverlight SDK on SL2, WS, and WCF, Sam Landstrom on using

Community Blogs

# W&ouml;chentliche Rundablage: WPF, Silverlight 2, ASP.NET MVC, .NET 3.5&#8230; | Code-Inside Blog @ Monday, March 31, 2008 12:04 PM

PingBack from http://code-inside.de/blog/2008/03/31/wchentliche-rundablage-wpf-silverlight-2-aspnet-mvc-net-35/

Wöchentliche Rundablage: WPF, Silverlight 2, ASP.NET MVC, .NET 3.5… | Code-Inside Blog

# Silverlight 2 - Passing Data Across Plug-In Instances @ Monday, March 31, 2008 1:20 PM

&lt;p&gt;Again, this falls into the category of &quot;just fo

Silverlight 2 - Passing Data Across Plug-In Instances

# Databinding XML in Silverlight 2.0 and more... @ Saturday, April 26, 2008 10:56 AM

Q: What do you get when you bring the data side of Mike Taulty&amp;#39;s brain together with the design side

Hot Topics