Rants Tagged with “Silverlight”

<<  <  3  4  5  6  7  8  9  10  11  12  13  >  >>  (Total Pages: 13/Total Results: 127)

Silverlight + ASP.NET AJAX = Good Times

I've been digging into the AJAX-Silverlight story a little more.  I wanted an example of something more business-like than what I have already crafted (the updating clock is an interesting demo but not very practical) so I decided to try and do a simple updating line graph.  This post is assuming you know a bit about ASP.NET AJAX and won't detail every step I took in creating the application (e.g. like creating the ScriptManager).  Here's what I wanted my chart to look like:

I created a simple XAML file to show my chart and created a Path object for each data line. I'll get into how I am updating the data in a minute.  First thing I did was change the way I am loading the Silverlight object. With the standard template (and most examples), the creation of the Silverlight object is done inside the div tag that will house the Silverlight. I took the cue from Fritz Onion's recent blog to use ASP.NET AJAX's pageLoad function instead:

// Known Function Name in AJAX to be called once the page has completed loading
function pageLoad()
{
  createSilverlight($get("myChart"));
}

I changed the call to createSilverlight to accept the object to be hosted in and I am using the $get AJAX shortcut to retrieving an element. Great, I now have the Silverlight chart in the browser but it doesn't show much yet. 

My expectation was to use an AJAX callback to get new data to show in my chart.  I toyed with the idea of creating a web service and actually getting data but in the end it made more sense to just use a PageMethod.  Page methods are static (or shared in VB) methods of a page that can be called instead of creating a separate web service.  To enable page methods, you need to tell the ScriptManager:

<asp:ScriptManager ID="theScriptManager" runat="server" EnablePageMethods="true">
  <Scripts>
    <asp:ScriptReference Path="silverlight.js" />
    <asp:ScriptReference Path="scene.xaml.js" />
    <asp:ScriptReference Path="default.aspx.js" />
  </Scripts>
</asp:ScriptManager>

Now that I enabled the page methods, I could create a new page method (called GetStats).  Notice the [WebMethod] is still required, but you do not have to create a whole web service:

public partial class _Default : System.Web.UI.Page
{
  // ...
  
  [WebMethod]
  public static List<double> GetStats()
  {
    Random rnd = new Random();
    List<double> results = new List<double>(4);
    results.Add(rnd.Next(100));
    results.Add(rnd.Next(100));
    results.Add(rnd.Next(100));
    results.Add(rnd.Next(100));

    return results;
  }
}

Instead of getting real data, I am just creating four random (or pseudo-random) data points that I can return to the page.  The idea here is that I have four new points (one for each color).  I want to add a new data point to each of the line graphs over time.  So this method can be used to get a new set of data.

Now onto the Silverlight code.  I have a JScript class that is where most of the guts of the real work is being done.  First in my OnLoad event handler I am retrieving each of the lines (Paths) so I draw them later as we have new data. (Note, I am actually putting them in an array to make the code a bit more streamlined).  I am also grabbing the height of the control to use for calcuations later and setting the initial set of data (starting out with four zeros).  Finally, I am calling a function that will get the first set of data:

SilverlightChart.Scene.prototype =
{
  handleLoad: function(control, userContext, rootElement) 
  {
    this.control = control;
    this.result1 = rootElement.findName("result1");
    this.result2 = rootElement.findName("result2");
    this.result3 = rootElement.findName("result3");
    this.result4 = rootElement.findName("result4");
    this.results = [this.result1, this.result2, this.result3, this.result4];
    this.height = rootElement.height;
    this.data = [[0], [0], [0], [0]];
    this.getNewStats();
  },

The getNewStats function is interesting because all it does is call the page method (Note: that all page methods are created with a PageMethod namespace to make calling them simple).  All web service calls are asynchronous so the parameter of the page method is a delegate to another function to call.  I am using the createDelegate call to allow me to use a function inside my JScript class for the callback.  If you were using simple JScript functions, you could just specify the name of the function:

getNewStats: function()
{
  PageMethods.GetStats(Silverlight.createDelegate(this, this.getStatsComplete));
},

Once the method is executed it calls our getStatsComplete function.  This funciton goes through and adds the new data (the result is the data that you returned from the page method) to our array of data. Then it calls a function that actually calculates the look of each line.  Finally it uses setTimeout to act as a timer and call the getNewStats function again after two second (2000 milliseconds) have elapsed.  This allows our new chart to get new data approximately every two seconds and will continue to grow as long as the user stays on the page:

getStatsComplete: function(result)
{
  for (var x = 0; x < 4; x++)
  {
    this.data[x].push(result[x]);
  }
  this.calculateGraph();
  setTimeout(Silverlight.createDelegate(this, this.getNewStats), 2000);
},

The last two pieces of functionality are the calculateGraph and formatData functions.  The calculateGraph function changes the entire data element of each of the lines to a new set of data for the Path object. This is inefficient but this is necessary because currently you cannot add elements to the children of a Path's Data element. To get around this limitation we simply use the formatData function to build a string using the Path's markup syntax to describe our particular line:

calculateGraph: function()
{
  for (var x = 0; x < 4; x++)
  {
    // Create by Creating the Data Block
    this.results[x].data = this.formatData(this.data[x]);  
    
    // Create by adding elements to the geometry *** DOESN'T WORK ****
    //this.results[x].data.children;	    
  }
},

The formatData function just takes a set of values (that we appended earlier) for a line and composes a complete data string. Of particular interest is that the Path's Data syntax does *not* have to be pixel based.  In this case we are assuming all the data is zero to 100.  You should notice the beginning of every line starts with "M0, -100 M0,0".  The "M" in the Path markup syntax says Move (not draw).  This forces our Path to be 100 high (going from -100 to 0).  We then add the value pair by moving them over 5 points at a time and using the new data as a negative value.  The idea here is that coordinates are normally top-down, but our chart wants to show data bottom up (zero at the bottom and 100 at the top) so we are just use negative values to accomplish this:

formatData: function(values)
{ 
  var result = "M0,-100 M0,0";
  for (var i = 1; i < values.length; i++)
  
    result = result + " L" + (i*5) + ",-" + values[i];
  }
  return result;
}

This code might seem odd because the size of the path is wierd.  When we have two points, we have 0,0 as a point and lets say 5,-50 as a point.  That would seem awfully small but in the example it shows the data as wide as the chart.  What gives?  The trick is that when we created the Paths in the XAML file, we told them to stretch (using the Stretch="Fill" attribute).  By using a Width, Height and Stretch our Path's actual data does not have to reflect pixels at all.  You use more traditional data points and just stretch them to the right size:

...
<Path x:Name="result1" Width="320" Height="240" 
      Stroke="#FFFF0000" Data="M0,-100 M0,0" Stretch="Fill" />
<Path x:Name="result2" Width="320" Height="240" 
      Stroke="#FF0000FF" Data="M0,-100 M0,0" Stretch="Fill" />
<Path x:Name="result3" Width="320" Height="240" 
      Stroke="#FF008000" Data="M0,-100 M0,0" Stretch="Fill" />
<Path x:Name="result4" Width="320" Height="240" 
      Stroke="#FFD000D0" Data="M0,-100 M0,0" Stretch="Fill" />
...

Let me know if you have any questions about this example and have fun playing with Silverlight and ASP.NET AJAX together!

You can download a clean version of the code to play with here.

More Silverlight Videos

New on Silverlight.net are two more of my videos:

Take a look and let me know what you think!

Two new Silverlight Videos!

Two more of my videos are up on www.silverlight.net!  These videos are:

As always you can review all the videos i've done for Silverlight at http://wildermuth.com/silverlight!

Let me know what you think.

New Silverlight.net Video! "Silverlight Events"

A new Silverlight video of mine is up on Silverlight.net.  I cover how the basics of wiring up events in Silverlight

In case you haven't seen it yet, I have a list of all my Silverlight resources at http://www.wildermuth.com/silverlight!

New Article: "10 Things You Should Know About Microsoft's Silverlight"

My new article, "10 Things You Should Know About Microsoft's Silverlight" is now live. This article is for www.cio.com so the audience is decidedly management level.  I attempt to explain why its important to understand Silverlight (and perhaps why to wait for 1.1 to get started with it).  Let me know what you think!

Status of Moonlight

I am interested and excited about Moonlight. For those who are not familiar, Moonlight is a project to bring Silverlight (1.1 only) to Linux. Because Silverlight is so isolated into a single plug-in, I was surprised how much was actually required to get it working (in its early development phase) on Linux. The biggest surprise was that Mono is required to make it work. They've abandoned the entire "mini-CLR" approach and are just layering on top of their Linux CLR implementation.  Probably not a bad strategy but it does mean there are more moving parts for installation.  Perhaps since I am not a Linux-head, those users will be more comfortable to install a number of moving parts to get it to work on thier machine.  I'd prefer to see a MS-driven mini-CLR on the Linux/Unix platform.

As I read it, to get started with Moonlight you need:

  • Install Mono 1.2.4.
  • Apply a Mono Patch for Moonlight.
  • Install the Olive (.NET 3.0) package for Mono.
  • Install GDK+.
  • Install Cairo.
  • Install ffmpeg.
  • Install Mozilla NSPR, NSS and XPCOM development packages.
  • Install Alsa.
  • Get the Moon source.

I hope this is just going to be for the developer.  I'd love to see the end-user experience be better than this.

While complaining about an open-source effort is fairly fruitless (I know, why don't I get involved...there is a long list of reasons I won't delve into here), I think its important to let the community at large understand how Miguel and company are approaching Silverlight.  Most notibly they are skipping Silverlight 1.0 entirely.  That's an important story I think.

What do you think?

Sweet...Silverlight and MLB

via Mike Harsh's Blog...

MLB has released a Silverlight RC based video player.  Take a look at Mike Harsh's Blog for the meat of the details...

Silverlight Tour - Expanding

We are proud to announce that the Silverlight Workshop Tour has added two new dates:

  • Atlanta, GA - October 15-17, 2007
  • Phoenix, AZ - January 21-23, 2008

Sign up today at www.silverlight-tour.com!

Silverlight 1.0 RC2 Being Pushed Out Today...

Tim Sneath reports that Silverlight 1.0 RC2 is going out today.  While reporting that it is not to fix a security fix, he explains that it is mostly to test-out the update scheme the Silverlight uses.  It looks like it is a 'runtime-only' update.  Doesn't look like the SDK or code is affected. Hopefully they'll stick to thier promise of not introducing breaking changes as of RC.

Read the link for the full scoop!

Silverlight Workshop - The Tour!

We are taking the Silverlight Workshop on the road.  Between now and January, we will be taking my Silverlight Three-Day Workshop on the road.  We will be holding the Workshop in Boston, Washington, DC, Dallas, Chicago, San Francisco and Seattle.  Please visit the tour's website at http://www.silverlight-tour.com for more information.