WPF/E and Script#

A whole bunch of technologies working together - AJAX, Script#, JSONP, and the just announced, WPF/E client runtime that enables scriptable media and vector graphics in the browser...

Earlier today, the first CTP of WPF/E was announced which enables some compelling AJAX scenarios by providing cross-platform and cross-browser scriptable media and vector graphics based on XAML markup. It is personally exciting to be working in this space, and see the technology address some items from my browser and scripting wish list that I blogged about back in May. There have been a few other blog posts on this announcement earlier today such as the ones posted by Scott Guthrie, Mike Harsh, and Shawn Burke.

I built a WPF/E-based Flickr application to demonstrate the confluence of HTML, XAML and scripting. The application uses the JSON services offered by Flickr to search for some images by tags, and then display the resulting set of pictures in a WPF/E powered presentation. Here is a screenshot which links to a live running sample. Be sure to visit the WPF/E page, and install the browser plugin before viewing the sample for now.

The sample shows off some basic usage of WPF/E elements, scripting against them, and animating them. The other interesting aspect of this sample is that I didn't write a single line of script. Instead all the code was written in c# and compiled using script#.

The latest release of Script# (0.2.0.0), also published today, contains a code-behind model that allows me to add c# code-behind to a page, and have that converted into script. I'll blog more about that in the coming days, but this post is mostly about WPF/E.

Here is a portion of my Scriptlet class, which contains c# code-behind for the page. The code in bold shows the scriptlet instantiating a WPF/E plugin instance with some XAML markup.

using System;
using System.DHTML;
using System.WPFE;
using ScriptFX.UI;

namespace PhotoViewer {

    public sealed class PhotoViewerScriptlet : IDisposable {
        private PhotoViewerControl _photoViewerControl;
        ...

        public static void Main(Dictionary arguments) {
            PhotoViewerScriptlet scriptlet = new PhotoViewerScriptlet(arguments);
        }

        private PhotoViewerScriptlet(Dictionary arguments) {
            ...
            Button searchButton = new Button((DOMElement)arguments["SearchButtonElement"]);
            searchButton.Click += OnSearchLinkClick;

            WPFEPlayer player =
                WPFEFactory.CreateWPFEPlayer((string)arguments["ID"],
                                             (DOMElement)arguments["ParentElement"],
                                             (string)arguments["MarkupURL"],
                                             "Black", /* windowLess */ true);
            _photoViewerControl =
                new PhotoViewerControl(player, (string)arguments["FlickrKey"]);
            ...
        }

        private void OnSearchLinkClick(object sender, EventArgs e) {
            string[] tags = _tagsTextBox.Text.Trim().Split(' ');
            _photoViewerControl.Start(tags);
        }

        ...
    }
}

And here is some code from the PhotoViewerControl that wraps the WPF/E plugin and implements the functionality to make requests to Flickr and progress the presentation from one photo to the next.

internal sealed class PhotoViewerControl : IDisposable {

    private WPFEPlayer _player;
    private string _flickrKey;

    private Image _photo1;
    private TextBlock _title1;
    private Storyboard _storyboard1;

    private HTTPRequest _request;

    private Photo[] _photos;
    private int _nextPhoto1;

    public PhotoViewerControl(WPFEPlayer player, string flickrKey) {
        _player = player;
        _flickrKey = flickrKey;
    }

    public void Initialize() {
        _photo1 = (Image)_player.FindName("image1");
        _title1 = (TextBlock)_player.FindName("title1");
        _storyboard1 = (Storyboard)_player.FindName("storyboard1");
        ...
    }

    public void Start(string[] tags) {
        Dictionary scriptTransportParams = new Dictionary();
        scriptTransportParams["callbackParameterName"] = "jsoncallback";

        string uri = String.Format(FlickrSearchURLFormat, _flickrKey, tags.Join("+"));
        uri = HTTPTransport.CreateURI(uri, typeof(ScriptTransport), scriptTransportParams);

        _request = HTTPRequest.CreateRequest(uri, HTTPVerb.GET);
        _request.Invoke(OnRequestComplete, null);
    }

    private void OnRequestComplete(HTTPRequest request, object userContext) {
        IHTTPResponse response = request.Response;

        if (response.StatusCode == HTTPStatusCode.OK) {
            PhotoSearchResponse searchResponse = (PhotoSearchResponse)response.GetObject();
            _photos = searchResponse.photos.photo;
            StartInternal();
        }
    }

    private static string CreateFlickrPhotoURL(Photo photo) {
        return String.Format(FlickrPhotoURLFormat, photo.server, photo.id, photo.secret);
    }

    private void ShowFirstPhoto() {
        _photo1.Source = CreateFlickrPhotoURL(_photos[_nextPhoto1]);
        _title1.Text =  _photos[_nextPhoto1].title;
        Window.SetTimeout(StartFirstTimeline, 1000);

        _nextPhoto1 += 2;
        if (_nextPhoto1 >= _photos.Length) {
            _nextPhoto1 = 0;
        }
    }

    private void StartInternal() {
        _nextPhoto1 = 0;

        ShowFirstPhoto();
        Window.SetTimeout(ShowSecondPhoto, 8000);
    }

    private void StartFirstTimeline() {
        _storyboard1.Begin();
        Window.SetTimeout(ShowFirstPhoto, 14000);
    }
    ...
}

One other thing to observe in the sample... the sample makes requests to the Flickr service directly without going through a server-side proxy. To make these cross-domain calls successfully, It uses <script> tags rather than XMLHttp to work against Flickr, and uses the JSONP support provided by the service. Script# provides a mechanism to work against this protocol transparently by hiding away the plumbing in the ScriptTransport class that is referenced in the code above. If this is of interest, drop me a comment, and I'll blog about it further.

The sample is packaged into the Script# msi that you can download to delve into the code. In addition to this sample, the msi contains the Script# compiler, and various other samples. There is also a document with a how-to guide on using Script# with a lot of new content, that should help you get up and running using the installed project templates.


[ Tags: | | | ]
Posted on Monday, 12/4/2006 @ 11:26 PM | #Script#


Comments

20 comments have been posted.

Marc Hoeppner

Posted on 12/5/2006 @ 12:18 AM
Honestly Nikhil, this stuff you do is pure gold. Very well done. Now, the only thing missing for me is having Script# understand the Atlas framework, so we can use all the great ASP.NET Ajax controls/extenders etc. Is there any chance you can make this happen soon? - Like tomorrow ;)

RichB

Posted on 12/5/2006 @ 12:31 AM
Hi,

I can't get it working in Safari. The text is white-on-white and the search button does nothing. I hope this is a pit of success technology, not a write-once-test-everywhere technology.

Ben Hall

Posted on 12/5/2006 @ 2:16 AM
Great stuff, I was wondering if this was going to be mentioned. I was going to have a play with it last night but I have an exam in an hour so really had to get some sleep.

Going to have to try this later tonight.

Alper Sunar

Posted on 12/5/2006 @ 6:43 AM
Is it possible to use Script# with a web application project rather than a website?

Scott Weeden

Posted on 12/5/2006 @ 8:44 AM
YAY a new version! Been waiting so patiently.... Can't wait to start toolin around.

Soven Shrivastav

Posted on 12/5/2006 @ 11:46 AM
This is awesome! Great work.

Shahin

Posted on 12/5/2006 @ 1:33 PM
Do we really need to break the web standards for this? Back to 90's...

Roman

Posted on 12/6/2006 @ 1:49 AM
It seems, Scriptlet code editor does not works properly - strange compiling errors occur and exception after "save and close"...

Jerod Moemeka

Posted on 12/6/2006 @ 2:09 AM
Hi,
this is the MOST RELEVANT microsoft technology to be released since .NET. I don't know if you work for Microsoft or not. If you do, please let them know this is the type of technology developers and architects need! Javascript is great but to me it's the new assembly langugae fro the web, we need code in a much richer format compiled down to javascript rather that doing it all by hand. THIS IS GENIUS! (Thank you ) - squared.

Rupak Ganguly

Posted on 12/6/2006 @ 2:39 PM
U DA MAN. This is excellent. Now, I can showcase my WPF stuff on the browser as well. Not soon that this will be mainstream. Script#, I need to read your guide first - to comment. Keep up the good work.

Fayez AlMutairi

Posted on 12/6/2006 @ 2:54 PM
I have downloaded the WPF/E CTP & SDK, I played with them and have noticed that WPF/E does not fully support Unicode, as I use a TextBlock to test the display of Arabic text, WPF/E was rendering the text incorrectly as if it is rendering the text from left to right while it should render the text from right to left. This same behavior is true for Hebrew too which is also a right-to-left language.

Chris Fazeli

Posted on 12/7/2006 @ 7:01 PM
Could you give me some pointers on how to go about creating a Scriptlet-like control for a different application server (most likely Tomcat/JSP)? Should I run reflector on a particular assembly? Am I even headed in the right direction?

I'd also love to hear about how you handle the cross-domain scripting w/o XMLHttpRequest. I'm about to run into a problem like this and would much rather not do any proxying.

Awesome stuff. Thanks.

Scott Weeden

Posted on 12/8/2006 @ 12:01 PM
Nikhil,

Is it bad to be using the objects outside of the ScriptSharp Application class? We have a master page that uses some script sharp objects and then also some child pages that use script sharp objects. We've been instantiating the objects outside of the application.run:

<script>
var t = new MyNameSpace.MyScriptSharpObject($('domid1'));
</script>

Will I run into any problems with resource cleanup... etc?

Nikhil Kothari

Posted on 12/10/2006 @ 4:56 PM
Chris: I will blog soon about cross-domain requests.
A scriptlet server control does couple of things - output some bootstrapper script that starts executing your script, and optionally performs compilation on the fly. You can write an equivalent for any server technology to do the first part. The second part requires calling into the script# compiler, which is a .net class, and may or may not be possible from other server environments, but you could use precompiled scriptlets, so it shouldn't get in the way.

Scott: You can create objects outside Application... sure. You just need to figure out where and when to dispose them. Your objects can register with Application by calling RegisterDisposableObject regardless of where they are created, to ensure they are disposed. You can explicitly call dispose on them earlier to free up memory before page unload as well...

Dion

Posted on 12/11/2006 @ 6:53 AM
Hi Nikhil, your projects.nikhil.net server seems to be down. I'm very interested in trying out Script#.

Emmanuel

Posted on 12/20/2006 @ 9:00 AM
Nik,

Wow! Not the WPF/E but the Script#. We're all writing a ton more JS these days and on the project that I'm working on which is a large web 2.0 app, the JS is starting to get pretty tough to manage. Script# looks like a FANTATIC solution to my problems but...

Until we have a warm fuzzy about Script#'s roadmap and commitment from Microsoft (or some other company) to support it, I have no choice but to stay away from it. It would be great if you could blog on that aspect of Script#. I think you'll find that you get a ton more evangilists that way.

Nikhil Kothari

Posted on 12/21/2006 @ 6:50 PM
Emmanuel - still working on what you bring up - don't have anything concrete to say at the moment, but I know where you are coming from.

Vijay

Posted on 5/1/2007 @ 2:39 PM
Hey Nikhil,

When I install and try creating a new script# enabled web site, I get the following error. "The file ssfx.UI.Core.dll could not be found within the project templates. Continuing to run, but the resulting project may not build properly"
Has anyone come across this problem?
Thanks...

Greg Leonardo

Posted on 5/23/2007 @ 5:05 AM
Hey Nikhil,
I am have the same issue "The ssfx.UI.Core.dll could not be found within the project templates. Continuing to run, but the resulting project may not build properly." message as the above user.

Thanks...Greg

Wei Wang

Posted on 8/4/2008 @ 4:41 PM
Hi Nikhil,

I am trying out the latest version of Script# and I think it is a great product. But I have the following problem with the scriptlet code editor: I have gone through the sample from the documentation from http://projects.nikhilk.net/ScriptSharp/Content/ScriptSharp.pdf. It seems that "Save and Close" convert all double quote " to &quot; which causes the build to fail. Also it occationally strips the using statements from the top of the code block, or some lines from the bottom. Only after I manually edited the code block in Source view (then I loose the intellisense) was I able to make the program work as expected.

Did I do anything wrong?

Thanks
Wei
Post your comment and continue the discussion.
 
 
 

 

 
Refresh this form if the spam-protection code is not readable, or has expired. (Your input will be preserved)