Wednesday, March 14, 2012

Get A Silverlight Control's Current Instance For Communicating Via The HTML Bridge

If you have a SilverLight control on an ASP.NET webpage, odds are eventually you will need to communicate with it, and this is done via JavaScript and the HTML Bridge. However you might find that the accessing the control's current state after user manipulation is not as straight forward as the documentation from the MSDN indicates.

In the MSDN and most examples, the suggestion is made that you explicitly register an instance of a scriptable type (your control's class) in the App class or the Page class. However there is a big difference on these (2) and also in the exact instance that you choose to register.

If in my control the main class is named 'MySLControl', so I decide to register its type in the 'Application_Startup' event of App.xaml like below:

Dim _MySLControl As New Silverlight.Custom.MySLControl
HtmlPage.RegisterScriptableObject("SLControl", _MySLControl)
The above will work perfectly and you will then be able to access your exposed <ScriptableMember()> types from JavaScript. However, there is a catch - the registered instance is a New instance of MySLControl so it will not contain the state of the control when called by JS.

So let's say you have a custom built online MP3 player you built with a 'Playlist' created by the user within the control. You want to use the HTML Bridge from your hosting ASP.NET app to communicate with the control and get some details on the playlist. If you access the registered control instance as coded above, you will not have access to any of the control's state after the user has interacted with it. Why? We registered a New instance and are not using the actual control's instance.

The change is (2) fold: First, move the registration of the type to a late event in the Page (control) itself like a wired up 'ControlLoaded' event as typical for many Silverlight controls. Second, register the current instance of the control and not a new instance. The code is displayed below:

Private Sub ControlLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
'Register this control type so it can be accessible via JavaScript.
'This allows other platforms like ASP.NET to have a medium to communicate and raise events within the control.
'MUST use this instance or the current control state will not be accessible by the JS calling it via the HTML bridge.
HtmlPage.RegisterScriptableObject("SLControl", Me)
End Sub
The result? When you access your Silverlight control via JavaScript you will have access to the control in its current state including any interactions or manipulation done to the control by the client.


Post a Comment