Tuesday, April 01, 2008

Subscribing to Silverlight Managed Code events from JavaScript

In Silverlight, it seems that most of the time, you need to reach into the hosting page from the managed world, but what if you want to reach into the managed world from the hosting page?  In other words, what if you want to subscribe to a managed event from JavaScript?

Let's look at an example.  Suppose we have a button in our Silverlight application for which we want our web page to respond.

XAML:

   1:  <Button x:Name="Button1" Height="35" Width="120" Content="Do Something" Click="Button1_Click" />

C#

...
   1:  public partial class Page : UserControl
   2:  {
   3:      [ScriptableMember]
   4:      public event EventHandler ButtonClicked;
   5:   
   6:      public Page()
   7:      {
   8:          InitializeComponent();
   9:          HtmlPage.RegisterScriptableObject("ScriptablePageObject", this);
  10:      }
  11:   
  12:      private void Button1_Click(object sender, RoutedEventArgs e)
  13:      {
  14:          if (ButtonClicked != null)
  15:          {
  16:              ButtonClicked(sender, e);
  17:          }
  18:      }
  19:  }
... 

Pay special attention to the ScriptableMember attribute that has been applied to the ButtonClicked event.  This causes Silverlight to expose the the type to the hosting page.  The RegisterScriptableObject call tells Silverlight to expose the containing type using the alias 'ScriptablePageObject'.

Now, we just need to subscribe to the exposed event on the JavaScript side:

...
   1:  <asp:Silverlight 
   2:      ID="Xaml1" 
   3:      runat="server" 
   4:      Source="~/ClientBin/CallHtmlDom.xap" 
   5:      OnPluginLoaded="pluginLoaded"
   6:      Version="2.0" 
   7:      Width="100%" Height="100%" />
   8:  </div>
   9:  </form>
  10:  <script type="text/javascript">
  11:   
  12:      function pluginLoaded(sender,args) {
  13:          var slCtl = document.getElementById("Xaml1"); 
  14:          slCtl.Content.ScriptablePageObject.addEventListener("ButtonClicked", jsEventHandler);
  15:      } 
  16:      
  17:      function jsEventHandler(sender, args) {
  18:          alert("Button Clicked");
  19:      }
  20:      
  21:  </script>

Once the Silverlight plugin has loaded, pluginLoaded is called which, in turn, registers the JavaScript event handler.  Enjoy!