Tuesday, November 27, 2007

Silverlight Preloader animation is the answer

I got this email today:

Hi!
In our project we call a function which retrieves a data from a webservice.
This function takes some time 1-3 seconds.
This we do in the end of the OnLoad event.
This causes the application not to appear immediately and is not drawn until the retrieve function is finished.
How can we let the application finish rendering and then invoke the retrieve function?
Then we could put up a message to ask the user to wait while loading.
Is there any onRendered event in Silverlight?
Or could be put a custom event back to the event queue some how, then we could emit an event which calls the retrieve function after the rendering is finished?
Best regards,
Haraldur


In most complicated Silverlight applications I generally have a preloader animation. So when the silverlight application first loads it shows some little animation that runs on the canvas loaded event until some other method is called that stops the animation and fades in the UI etc.

Using the downloader object this is pretty straight forward as you can add a delegate to the downloader object and then the delegate gets called when the download is complete and it can do something to get the application running. a simple example is:

var downloader = this.control.createObject("downloader");
downloader.addEventListener("completed", Silverlight.createDelegate(this, this.MediaClipDownloadCompleted));
downloader.open("GET", "control/MediaClip.xaml");
downloader.send();

in this case the downloader is pulling some xaml but really it could be anything. when complete the method 'MediaClipDownloadCompleted that in this case looks like this:

MediaClipDownloadCompleted: function(sender, eventArgs)

{

var xamlItem = sender.getResponseText("");

MediaClipClass = new MediaClipBaseClass( xamlItem );

MediaClipClass.LoadTarget( this.control.content, this.root.findName("MediaTarget"), 50, 100, "test/sample.wmv", "test/thumb.png" );

}

anyway working with the HTTPRequestObject is similar. take this code for example:

this.HTTPRequestObject.open("GET", this.url, true); this.HTTPRequestObject.onreadystatechange = this.XMLObjCallback; this.HTTPRequestObject.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); this.HTTPRequestObject.send(null);

basically we set the 'onreadystatechange' to our delegate that deals with things when the request is returned. In this case the method looks like this:

XMLObjCallback: function( )
{ // Check for the completed status
if (_XMLRef.HTTPRequestObject.readyState == 4)
{ // Check for successful server response
if (_XMLRef.HTTPRequestObject.status == 200)
{
if( _XMLRef.XML == "" )
{
_XMLRef.XML = _XMLRef.HTTPRequestObject.responseText;
}
if (!window.ActiveXObject)
{
var parser = new DOMParser();
_XMLRef.XmlDocument = parser.parseFromString(_XMLRef.XML,"text/xml");
}
else //is i.e
{
_XMLRef.XmlDocument = new ActiveXObject("Microsoft.XMLDOM");
_XMLRef.XmlDocument.async = "false";
_XMLRef.XmlDocument.loadXML(_XMLRef.XML);
}
}
else
{ // HTTP error
alert('Error: ' + _XMLRef.HTTPRequestObject.status);
}
}
},

its a bit complicated but basically when the code returns it does its thing. For more information on XML see these previous posts:

http://hackingsilverlight.blogspot.com/2007/10/parsing-xml-in-silverlight-10-cross.html

and this code sample

http://www.HackingSilverlight.net/samples/XMLParser.zip

also look at some of the bits in 1.1 and hopefully the new 1.1 drop that comes soon will have some more goodness for us.

No comments:

Post a Comment