Bruggen bouwen in Silverlight
Met de komst van Silverlight hebben we een interessant ontwikkel platform tot onze beschikking gekregen waarmee we .NET applicaties in de browser van de cliënt kunnen uitvoeren. Deze applicaties maken gebruik van een subset van de base class library van het .NET Framework en worden uitgevoerd door de Common Language Runtime (CLR) van de Silverlight plug-in. Doordat deze Silverlight plug-in voor diverse browser/OS combinaties beschikbaar is is je Silverlight applicatie direct browser en OS onafhankelijk.
Hosting pagina
Silverlight applicaties worden gehost in een webpagina, dat kan een ASP.NET pagina zijn maar dat mag ook een gewone HTML pagina zijn. De Silverlight applicatie zelf draait in een sandbox geheel onafhankelijk van deze pagina.
Er zijn ook situaties denkbaar waarbij een Silverlight applicatie niet stand-alone draait maar onderdeel uit maakt van een groter geheel. Een online routeplanner kan bijv. geheel in ASP.NET gemaakt zijn met uitzondering van het tonen van de kaarten. Stel dat je het weergeven van de kaarten met Silverlight zou willen doen, dan zou je vanuit je hosting pagina de Silverlight applicatie willen benaderen of vice versa. Dit is het moment waar de HTML Bridge in beeld komt.
Met behulp van de HTML Bridge is het mogelijk om vanaf de hosting pagina via JavaScript .NET functionaliteit van Silverlight aan te roepen. Je hebt dan direct de beschikking over bijvoorbeeld Isolated Storage, de BackgroundWorker etc. Kortom genoeg redenen om eens wat gedetailleerder naar de HTML Bridge te gaan kijken.
HTML Bridge
De HMTL Bridge is het onderdeel van Silverlight dat interactie tussen de HTML Document Object Model (DOM) en managed code (.NET) mogelijk maakt. Denk hierbij bijvoorbeeld aan:
• HTML elementen van de hosting pagina benaderen.
• Een JavaScript event koppelen aan een managed eventhandler.
• Managed types (.NET) en members van managed types beschikbaar maken voor JavaScript.
In dit artikel worden verschillende eenvoudige voorbeelden geven van interactie m.b.v. de HTML Bridge van Silverlight. Het is bij de interactie niet noodzakelijk dat de Silverlight applicatie ook daadwerkelijk visuele elementen bevat. Je zou deze eventueel ook non-visueel kunnen maken en als container kunnen zien voor managed code die je beschikbaar maakt voor de hosting pagina.
“ Het is overigens hierbij niet noodzakelijk dat de Silverlight applicatie ook daadwerkelijk visuele elementen bevat”
Aan de slag
Op de hosting pagina is in de object tag van de Silverlight plug-in een parameter ‘enablehtmlaccess’ beschikbaar die aangeeft of je het gebruik van de HTML Bridge toe staat. Indien de parameter niet aanwezig is (dat is default het geval) wordt aangenomen dat je dit gewoon toestaat. Als je om security redenen dit niet wilt dan kan je de HTML Bridge expliciet uit zetten. Je kunt ook, zoals in Listing 1 te zien is, expliciet aangeven dat je dit toe staat.
<param name="enablehtmlaccess" value="true" />
Listing 1: EnableHtmlAccess parameter.
Als deze EnableHtmlAccess parameter op false staat dan krijg je in run-time een InvalidOperationException op het moment dat je toch gebruik probeert te maken van de HTML Bridge.

Fig. 1: Exception DOM/scripting bridge is disabled.
De HTML Bridge bestaat uit een aantal classes die zich bevinden in de System.Windows.Browser namespace. Je dient dan ook deze namespace toe te voegen aan code waar je de HTML Bridge wilt gaan gebruiken.
De belangrijkste classes van de HTML Bridge zijn:
|
HTMLPage
|
Verwijst naar de hosting pagina.
|
|
HTMLDocument
|
Verwijst naar het Document Object Model (DOM).
|
|
HTMLElement
|
verwijst naar een individueel element van de DOM.
|
Tabel 1: Overzicht belangrijkste classes van de HTML Bridge.
HTML elementen benaderen
Om vanuit Silverlight HTML elementen te benaderen maken we gebruik van de classes van de HTML Bridge. De code in Listing 2 benadert een HTML input button. De verwijzing naar dit element gebeurt op basis van zijn id (btnDemo).
Met behulp van de SetAttribute method van HTMLElement zijn we vervolgens in staat attributen van het element aan te passen. In dit voorbeeld wordt de HTML value attribuut aangepast zodat de tekst van de input button gewijzigd wordt.
HtmlDocument document = HtmlPage.Document;
HtmlElement demoButton = document.GetElementById("btnDemo");
demoButton.SetAttribute("value", "changed in Silverlight");
Listing 2: Een HTML input button benaderen vanuit Silverlight.
Naast SetAttribute() bevat HTMLElement ook een GetAttribute() method voor het opvragen van een waarde van een HTML attribuut.
Voor visuele wijzigingen die je normaal gesproken via het HTML style attribuut zou doorvoeren is er een aparte GetStyleAttribute() en SetStyleAttribute() method beschikbaar. In Listing 3 wordt de SetStyleAttribute method gebruikt om de breedte en font grootte van de button aan te passen.
HtmlDocument document = HtmlPage.Document;
HtmlElement demoButton = document.GetElementById("btnDemo");
demoButton.SetStyleAttribute("width", "400px");
demoButton.SetStyleAttribute("fontSize", "32px");
Listing 3: Style aanpassingen vanuit Silverlight.
Een managed eventhandler toevoegen
De HTML Bridge gaat verder dan alleen het aanpassen van HTML attributen. We kunnen bijvoorbeeld ook een managed eventhandler koppelen aan het onclick event van de input type button. Dit koppelen gebeurd d.m.v. de AttachEvent method, zie Listing 4.
private void ShowHTMLBridge()
{
HtmlDocument document = HtmlPage.Document;
HtmlElement demoButton = document.GetElementById("btnDemo");
demoButton.AttachEvent("onclick", new
EventHandler(this.DemoButton_Clicked));
}
private void DemoButton_Clicked(object o, EventArgs e)
{
MessageBox.Show("Demo button Clicked");
}
Listing 4: Een managed eventhandler koppelen.
Als we Listing 4 uitvoeren wordt een Silverlight MessageBox getoond als we op de HTML input button klikken.
“De HTML Bridge gaat verder dan alleen het aanpassen van HTML attributen. ”
JavaScript uitvoeren vanuit Silverlight
Het uitvoeren van een JavaScript functie vanuit Silverlight is vrij eenvoudig. Het enige wat we hoeven te doen is de Invoke method van de Window property van de HTMLPage Class aan te roepen met de juiste parameters.
HtmlPage.Window.Invoke("popup", String.Empty);
Listing 5: Een JavaScript functie aanroepen vanuit Silverlight.
In Listing 5 wordt de JavaScript popup functie aangeroepen vanuit managed code. Door middel van het tweede argument van de Invoke method kunnen eventuele parameters die je wilt doorgeven aan de functie via een params object array doorgeven worden.
De HtmlPage.Window property is van het type HtmlWindow en is de managed versie van een JavaScript Window object. HtmlWindow bevat een aantal handige methods, zie Listing 6 voor een aantal voorbeelden.
HtmlPage.Window.Alert("JavaScript alert");
string result = HtmlPage.Window.Prompt("JavaScript prompt");
HtmlPage.Window.Navigate(new Uri("
http://www.oosterkamp.nl"));
Listing 6: HtmlWindow methods gebruiken
De Alert method voert een JavaScript Alert dialog uit met daarin de opgegeven string. De Prompt method kan je gebruiken om input van de gebruiker via een JavaScript prompt op te vragen. De Navigate method zorgt ervoor dat de browser naar de opgegeven URL navigeert.
Let op: Een nadeel van het gebruik van deze functionaliteit van de HTML Bridge is dat je weer bedacht moet zijn op browser incompabiliteit. De Navigate method bijvoorbeeld werkte bij mij prima in Internet Explorer 8 en Firefox 3.5 Maar werkte niet in Google Chrome 3.0.
Managed code uitvoeren vanuit JavaScript
Het is ook mogelijk om managed code uit te voeren vanuit JavaScript. In Silverlight dien je dan door middel van attributen aan te geven dat een type of specifieke members van een type scriptable zijn.
[ScriptableType]
public class CalculationScriptableType
{
public int Calculate(int x)
{
if (x == 1)
return 1;
return x * this.Calculate(x - 1);
}
}
Listing 7: ScriptableType.
Het voorbeeld in Listing 7 bevat een class met het ScriptableType attribuut. Alle public methods, properties en events van deze class zijn dan te benaderen met JavaScript. Je kunt eventueel ook gebruik maken van het ScriptableMember attribuut om aan te geven dat niet de gehele class maar uitsluitend bepaalde methods, properties en events van de class scriptable zijn.
In dit voorbeeld bevat de class uitsluitend één public method Calculate die via recursie de faculteit berekent van een opgeven integer waarde.
Om een ScriptableType te kunnen gebruiken zal deze eerst nog geregistreerd moeten worden. Registreren kan door een instantie van het ScriptableType aan te maken en deze door te geven aan de static RegisterScriptableObject method van HTMLPage. De eerste string parameter van deze method bevat dan de key waarmee het ScriptableType vanuit JavaScript te benaderen is. Zie Listing 8.
public MainPage()
{
InitializeComponent();
CalculationScriptableType scriptType = new CalculationScriptableType();
HtmlPage.RegisterScriptableObject("CalculationScriptableType",
scriptType);
}
Listing 8: Het registreren van een ScriptableType in Silverlight.
Na registratie kunnen we de calculatie uit laten voeren vanuit JavaScript. Zie Listing 9.
<script type="text/javascript">
function ManagedCalculation() {
var SLPlugin = document.getElementById("SLPlugin");
var inputValue = document.getElementById("InputValueCalculation").value;
var result = SLPlugin.Content.CalculationScriptableType.
Calculate(inputValue);
document.getElementById("OutputValueCalculation").innerHTML = result;
}
</script>
<h1>ScriptableType demo</h1>
<table>
<tr>
<td>
<input type="text" maxlength="5" id="InputValueCalculation" />
</td>
<td>
<input type="button" id="btnDemo" value="Calculate"
onclick="ManagedCalculation()" />
</td>
</tr>
<tr>
<td colspan="2">
Result calculation:
</td>
</tr>
<tr>
<td colspan="2">
<span id="OutputValueCalculation" class="output"></span>
</td>
</tr>
</table>
Listing 9: Uitvoeren van managed code vanuit JavaScript
• De JavaScript functie ManagedCalculation() wordt aangeroepen als de input button ingedrukt wordt.
• Er wordt met de SLPlugin id verwezen naar de object tag van de Silverlight plug-in, deze dient deze id te bevatten.
• De aanroep: SLPlugin.Content.CalculationScriptableType.Calculate(…) zorgt er uiteindelijk voor dat de managed code wordt aangeroepen. De input parameter voor deze method is de waarde die men in de input met id: InputValueCalculation heeft opgegeven.
• Het resultaat van de berekening wordt toegekend aan de variabele result en deze wordt vervolgens getoond.
Het resultaat is te zien in Fig. 2. In dit voorbeeld bevat de Silverlight applicatie zelf dus geen visuele elementen, maar wordt uitsluitend gebruikt om de berekening managed uit te voeren.

Fig. 2: Resultaat managed code berekening
Conclusie
Met de HTML Bridge is interactie tussen Silverlight en de hosting pagina eenvoudig te realiseren. Je Silverlight applicatie kan hierdoor gebruik maken van reeds aanwezige functionaliteit en optimaal integreren in een bestaande webapplicatie. Je kunt de HTML Bridge ook inzetten om vanuit JavaScript gebruik te maken van een managed code library die je in Silverlight ontwikkeld hebt. Door enkele eenvoudige voorbeelden uit te werken hoop ik dat je een goed beeld hebt gekregen van de mogelijkheden.
Referenties
Microsoft Silverlight: http://silverlight.net/learn/quickstarts/htmlbridge/
Microsoft MSDN: http://msdn.microsoft.com/en-us/library/cc645076(VS.95).aspx