Thursday, March 20, 2008

Silverlight 2: User Controls and Other Tips

Silverlight logo So I've started working in Silverlight and am completely blown away by it's power and ease of programming.  I'm not saying that there isn't a learning curve, there is with any new technology, but this one isn't too bad.  To be honest the hardest part of Silverlight 2 is finding information on it.  So with that said I'm going to pass on some of what I've learned over the last couple weeks.

First, the absolute best resource online currently is the forums over at Silverlight.net, there are people on there that really know their stuff and are happy to help out others.  You do need to register to use the forums but the same login/password you use at www.asp.net will work here as well.  I also recommend subscribing to the RSS feed of the latest blogs related to Silverlight, tons of good, knowledgeable people get cross-listed there.

So what am I working on?  First, this is what the project sponsors asked for:

rawbayface

As you can see it's boring.  No one cares about look in this application but still, we saw that and immediately thought of a nicer way of doing it.  So we convinced my manager to allow me to build a prototype screen for the feature using Silverlight 2.  He even gave the approval before the beta for Silverlight 2 was released.  So this is what I built: (Disclaimer:  If anyone is an NEC Unified Solutions customer the following screenshot is not in and may never be in a released product)

SilverBayface

Look a little nicer eh?  Basically it reads an XML document at runtime that it downloads from an ASP.NET application and then parses that data to create a series of controls.  The controls are one to four Stacks which can contain one or two Modules, each of which contain four Units.  The Stacks, Modules and Units are all specific to the application being built, which happens to be a piece of a PBX management application.  These are represented in the Silverlight application using custom User Controls defined for each piece.  The host application will have business objects that also relate to each of these Silverlight User Control classes.  Each of these user controls (Stack, Module and Unit) are added at runtime based on the downloaded XML document.  There are also more controls at a lower level and a couple of controls that are nothing but forms but for now lets concentrate on those three controls.

I'm not an expert by far, yet, but I have learned quite a bit about them and am very impressed.  In many ways User Controls in Silverlight are much more powerful than their ASP.NET counterparts.  You don't need to worry about state between actions for instance, this one piece took me a little while to figure out but once I did it is powerful indeed.  So here goes, some tips and pointers on Silverlight 2 User Controls.

First there are a couple of things you need to know for the code to make sense, LINQ and the way we're accessing global resources.

LINQ to XML

The normal XML namespace is not available in Silverlight so if you want to work with XML, you need to learn LINQ.  For me this was probably the hardest part of creating the prototype.  I've created and consumed many a XmlDocument in the past so moving to XDocument instead was a big step, it all looks foreign to me.  I struggled through it though and made it work, though I doubt someone that really knows LINQ to XML would think this code is "pretty".

You will be seeing LINQ to XML used in a few of the below samples but here is a taste:

rawlinq

In the above sample I am parsing the XML displayed below and returning a collection of slot elements.  It's different but makes a lot of sense one you get the hang of it.slotxml 

Accessing Global Resources

Another issue that needed addressed is that of accessing global resources.  This is one area where I had to go to the Silverlight.net forums for help.  I'm not sure if the answer I received and thus the approach that I took is the recommended approach, but it does work.  Basically the approach is to take create a singleton class that is loaded during initialization and then can be accessed ad modified from any level.

rawglobal

You will see this object used in some of the later code samples, at least now you will know what you are seeing.  It is all very simple, as is everything in Silverlight, once you figure out how to do it.

Now to the User Controls. 

User Controls are Real Objects

This is something that on the surface sounds like a no-brainer but when you really understand what it means is one of those things that changes the game.  For those of us coming from the web world pretty much all we have ever known is stateless programming.  All of our objects are one-time use and then you load it again if you need it again.  ASP.NET tried to mask this somewhat but the basic fact still remained.

With Silverlight 2 though any properties that you assigned values to still have those values when you next look at that object.  That sentence is a little hard to follow so let me try to explain. 

  1. Add custom properties to your new User Control when you create it.
  2. At runtime assign values to those properties.
  3. When responding to events at a later time those properties still have the value that was assigned.

The above doesn't sound that big but when you have multiple instances of the user control and each instance has unique values assigned to it's properties, the usefulness becomes much more apparent. 

To illustrate this here is a custom User Control I created for the prototype.  This is one of the simplest user controls but it illustrates the points.unitxaml

As you can see it has a very simple presentation, nothing but a square with some text on it, both of which call the same click event handler.  Now for the (truncated) code behind for that same control:rawunitcode

The class is derived from UserControl and defines a number of properties.  It also has a second constructor which initializes those same properties.  Nothing unusual here.  Here is an event handler accessing the properties declared above:rawunitevent

In this sample you can see that we are using the GlobalVariables singleton to obtain a reference to the root element of the XAML.  We then are using some of the values from the active instance of the Unit class to initialize an editable form, even passing in a reference to itself.

Programmatically Adding User Controls

For many dynamic applications you will not know at design-time the exact number of a given piece of your application.  This creates the need to add a given number of said element at run-time.  Enter Programmatically added user controls.

Adding a user control from code is quite simple and very similar to doing the same operation in ASP.NET.  You basically add the new user control to the children collection of some parent object.rawpage

After seeing how the controls are added, the code above of the event handler accessing the assigned properties should make a lot more sense.  You don't have to do any special coding to determine which object was clicked, as it is the actual object you created earlier.  This is a wonderful thing for all of us ASP.NET developers used to loading objects on each postback.

In a real world deployment there may be more logic happening here but this is all it takes to do this.  As you can see it is as simple as creating an instance of the control and then adding it to the parent.  One thing you may have noticed is the use of LINQ to XML, there is a reason for that that I will cover next.

Other Tips

  • Don't put a name on the root level control in your User Control or there can be only a single instance of it in the Silverlight application.
  • Learn LINQ.  I know I already mentioned this one but if you are going to be doing much Silverlight development it is a good thing to know.
  • Use Generic collections.  The Silverlight version of the CLR does not support the "old" collection types like ArrayList so get used to working with the new Generic collections like List<>.  Personally I prefer these anyway.

Final Thoughts:

So this was my first real taste of Silverlight development and all I can say is "WOW".  I already thought that this was going to be a game changer and now I am completely convinced.

This post has become a little longer than I had intended but I feel it is all good information for the ASP.NET developer getting started in Silverlight.  I will be posting more on Silverlight, and I'll also be giving some talks on it that will be announced in the near future.  This is an exciting time to be a web developer!

If you would like more information on this please comment on this post or ask me by another means.  I'll also be giving a presentation on April 22nd for the Cleveland C#/VB.NET Special Interest Group and again on May 17th at Cleveland Day of .NET with this same application as the base for the demos.

kick it on DotNetKicks.com

4 comments:

David Good said...

First Post...[ahem] Comment!!!

David Good said...

Um. You might want to expound on Stacks, Modules, and Units a bit, so as not to confuse people with PBX vs. CS terminology.

David

John Stockton said...

David,

Good idea, I've updated that section to make the distinction clearer.

Unknown said...

Hi John,
Do you have any Idea how we can manage state between Silver light user control and Web pages?
What I am trying is that I have a designed a grid in silver light that displays some relevant information about a coustomer now on click of a link in this control I want to pass customer ID of the selected customer to a web page wherein I can see all the data about the customer along with the edit functionality.