From Silverlight to Javascript and Back AgainThe Scriptable Attributes![]() Silverlight & IronPython
The Scriptable Attributes
We can call into Silverlight from Javascript using one technique, and a slightly different one for calling from Silverlight into Javascript. Both of them are based on marking classes and methods with .NET attributes. Unfortunately we can't set attributes from IronPython, so we have to use a bit of C#. Fortunately we can create a stub-class, and then subclass from IronPython. The C# is simple enough that, even if you have never seen C# before, you should be able to understand it. The Scriptable attributes lives in the System.Windows.Browser namespace. C# can be compiled using Visual Studio 2008 professional. You will also need Visual Studio tools for Silverlight installed. Fortunately you don't need these installed to compile assemblies for Silverlight - we'll see how in a few moments. Scriptable C# ClassC# for a Scriptable class with a Scriptable method that takes and returns a string look like:
using System;
using System.Windows.Browser;
[ScriptableType]
public class ScriptableForString
{
[ScriptableMember]
public string method(string value)
{ return this._method(value); }
public virtual string _method(string value)
{ return "override me"; }
}
This uses the ScriptableType and ScriptableMember attributes We need a Scriptable class with a Scriptable method. This should call down to a virtual method that we can override in an IronPython subclass. If we want to pass and return arguments they need to be strongly typed, and can only be a primitive like a string or an integer. This isn't really a problem though because we can pass or return JSON as a string. There is a JSON serializer and deserializer available in Silverlight, and using it from Javascript is easy of course! Using from IronPythonTo use this from IronPython we need to import the class from the assembly we have compiled. To add a reference from the assembly, we have to use the full name: import clr clr.AddReference("Scriptable, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null") from Scriptable import ScriptableForString class SomeClass(ScriptableForString): def _method(self, string): ... return new_string some_class = SomeClass() Registering the Scriptable ObjectBecause our scriptable object needs to be visible from both IronPython and from Javascript we need to register it. from System.Windows.Browser import HtmlPage HtmlPage.RegisterScriptableObject( "someClass", someClass ) Calling from JavascriptOnce we have registered the scriptable object, it is then available on the control to be called from Javascript. (This is made easier by giving the Silverlight control an id in the object tag in the html.) control = document.getElementById( 'SilverlightPlugin' ); result = control.Content.someClass.method( value ); C# Scriptable EventThe techniques we have just looked at are fine for calling from Javascript into Silverlight. To go the other way (from Silvelright calling into Javascript) we need to create a scriptable event.
using System;
using System.Windows.Browser;
[ScriptableType]
public class ScriptableEvent
{
[ScriptableMember]
public event EventHandler Event;
public virtual void OnEvent(ScriptableEventArgs e)
{
Event(this, e);
}
}
This scriptable event needs to work with scriptable event args.
[ScriptableType]
public class ScriptableEventArgs : EventArgs
{
private string _val;
[ScriptableMember]
public string val
{
get { return _val; }
set { _val = value; }
}
}
We need to register this on both the IronPython and the Javascript side. The Javascript needs to attach an event handler to the event we have exposed. This handler will receive the eventargs we pass in from the IronPython side and be able to access the scriptable members we gave it. THe Javascript side can modify those members to return values. Using from IronPythonNo need to subclass this time. event = ScriptableEvent() # This must also be registered HtmlPage.RegisterScriptableObject( "event", event) args = ScriptableEventArgs() args.val = 'some string' event.OnEvent(args) The JavascriptIn order to use this event, we have to assign a Javscript function to the event exposed on the control. We can only assign one function to this event (no multicast). This function will receive two arguments (like normal .NET events), the sender and the event we pass in.
function some_function(sender, args) {
value = args.val;
...
args.val = new_value;
}
control = document.getElementById('SilverlightPlugin');
control.Content.event.Event = some_function;
When event.OnEvent(args) is called, the javascript function (some_function) is called and receives the arguments sender and our event args. The Javascript can modify the attributes on the event to return values. After the call returns, IronPython can look at the attributes on the event args to retrieve any return values. Compiling C# with NotepadHaving to download Visual Studio 2008 (and that is one hefty download) just to compile a few lines of C# is a nuisance. Fortunately we can get round this by using the .NET 2 compiler to do it for us. (I think that the compiler, csc.exe, comes with the .NET 2 SDK - but it may even be included in a normal .NET 2 install.) The following batch file tells csc to compile with references to the Sivlerlight DLLs instead of the standard framework ones. It compiles all the C# files in the directory (*.cs) into an assembly specified by the /out argument (/out:SilverlightApp.dll).
set sl=C:\Program Files\Microsoft Silverlight\2.0.30226.2
set csc=C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe
%csc% /out:Scriptable.dll
/t:library /nostdlib+ /noconfig /r:"%sl%\mscorlib.dll"
/r:"%sl%\System.dll" /r:"%sl%\System.Core.dll"
/r:"%sl%\System.Net.dll" /r:"%sl%\System.Windows.Browser.dll"
*.cs
pause
The lines that start %csc% need to be all on one line - I've split it into multiple lines here for readability. The paths I've included above are the paths that I found csc and the Silverlight assemblies on my machine (Windows Vista). You may need to modify them for yours. I haven't tried this with Mono on the Mac, but I would be interested to hear from anyone who gets it working (or otherwise). From compiling C# for use with IronPython, the next logical step is embedding the IronPython interpreter in a C# Silverlight application: For buying techie books, science fiction, computer hardware or the latest gadgets: visit The Voidspace Amazon Store. If you're looking for a new techie job, try the Voidspace Tech Job Board. This is part of the Hidden Network of technology and programming jobs.
Last edited Sun Jun 1 23:37:08 2008. Counter... |
|
|
Blogads
Follow me on: Tech Jobs |