Click here to monitor SSC
  • Av rating:
  • Total votes: 13
  • Total comments: 2
John Bower

Silverlight Skinnable User Interfaces

05 February 2008

John Bower demonstrates more of the features of Silverlight, and Expression Blend, and shows how one might write an application that avoids UI pitfalls by placing your design responsibility squarely on your users’ shoulders. If it looks bad, it’s their fault!

Back in 1997, I had my first encounter with User Interface design while I was working for a web development company in London.

I used to watch with awe as one of our senior C++ developers spent hours every day carefully shifting his buttons and textboxes around with neurotic precision, one pixel at a time. He spent more time fiddling about with the UI of the application than actually programming the thing. He also had a tendency to swear loudly every so often and stare at co-workers with a psychotic twitch in his left eye, which I’ve since found to be  a mannerism that's prevalent among many senior C++ developers.

I couldn’t help but think to myself, “it might look good to him as a programmer… but I wonder how quickly an office blood-bath would ensue if even one client emailed him saying the UI looks awful, and he wants it all different!” After all, you can’t please everyone, especially if they're customers.

My desk was the one that was closest to his, I didn't like that twitch and I was highly-strung. - I worried that I’d probably be the first to sustain collateral damage from a frenzied attack, and posthumously provide a Pollock-style splatter effect to the décor of the office. It was this bone-chilling fear of impending doom that first led me to contemplate the self-preserving benefits of a customizable User Interface.

Although Silverlight is quite capable of meeting most of your programming needs on its own, one of its common uses is simply as a front-end for a more advanced server-based application. This is where all of Silverlight’s multimedia power can be harnessed to create quite elaborate user interfaces. You could use this to make your web application feel more unique to users by allowing them to fully customize how it looks. For example: If, for whatever reason, a user found the colour Green repugnant – why would they want to use your bright Green application? Why not give them the opportunity to change it to Red? Or Purple? Or any other colour?

I wouldn't necessarily advise such a thing but it makes a useful demonstration of Silverlight's versatility, and gives us an excuse to use Expression Blend.

In this article we will create a Silverlight application that uses colour data retrieved from a Cookie in order for us to create a customizable User Interface, unique to each user.

We will cover:

  • Creating and loading User Controls
  • Editing User Controls in Expression Blend
  • Updating colour properties
  • Reading and writing Cookies on the user’s computer
  • Passing data from the host document to Silverlight

1. Getting Started

For anyone who has been following this series of articles, we’re finally going to use Expression Blend! If you haven’t got Expression Blend yet, go to http://www.microsoft.com/expression/ and download the latest preview version. As of the time of writing, it will be the December Preview.

Before we get to the drawing though, create a new Silverlight project in Visual Studio 2008. Give it a convenient name and then open the Solution Explorer.

Now we have our new blank project we can add a new User Control by right-clicking in the Solution Explorer and then selecting “Add > New Item…”

In the Add New Item window, select Silverlight User Control and enter a name for it, (I’ve cunningly called mine “button.xaml”), then click Add.

You’ll be presented with the XAML code for our blank User Control, but we won’t be editing it here. You could create your button using pure XAML code but it’s much faster, more precise, and far easier to edit it in Expression Blend.

To do this, right-click on the new Control and select “Open in Expression Blend…”

You’ll probably be asked if you want to save the project at this point. Just click the “Yes” button and Windows will start Expression Blend with the project ready to be edited.

2. Creating a button in Expression Blend

Expression Blend makes editing XAML mercifully simple. The only problem being that Blend can appear daunting at first-glance. If you’ve previously done any graphical work in Flash, you should find it fairly easy to get your head around once you know where everything is.

If you haven’t ever used Flash, don’t worry. Although you’ll probably find it a bit tougher to grasp, it actually follows a vaguely similar layout to Visual Studio with the addition of a few graphics, and animation features.

Either way, we’ll start from the very beginning for this tutorial. You should now be presented with a window similar to this one:

Here’s a quick tour of the four main sections shown above:

  1. The Objects and Timeline pane shows the layers of objects (Paths, Images, etc.) in your Control and changes to show the timeline of your Silverlight Control, if you add a Storyboard, enabling you to create key-frames for animation. At the moment we have a single Canvas acting as the root object of our Control.
  2. Preview pane shows what your Control looks like. You can draw new objects into this pane in a similar way to most graphics programs.
  3. The Project tab lists all the files contained within your project. Next to it is the Properties tab (which isn’t selected in the above image).
  4. The Code pane displays the XAML code behind your Control. This displays exactly what is within your XAML file and it’s pretty much just a text editor.

Obviously I’m just scratching the surface here, there’s much more to Expression Blend’s interface than these four panes, but these are the main sections we’ll be working with for this tutorial.

For the purposes of our project, let’s make a funky glass button using a few Path layers and some transparent gradients.

The first thing we need to do is specify the size of the button. Click on the White area in the Preview pane. This is our Control’s Canvas, and you should notice that clicking it selects the relevant section of XAML code and also the “[Canvas]” layer in the Objects and Timeline pane.

Click on the Properties tab and find the Layout category. Then change the Width and Height properties to 250, and 100 respectively. As our button will have rounded edges it’s a good idea to make the Canvas transparent allowing the background of the application show through, so drag the A (alpha) slider down to 0% in the colour editor.

Setting the Opacity for our Canvas will affect all its child objects, so make sure it’s left on 100%. You could use this parameter to fade the Control in and out if you wanted to, but let’s not go too crazy just yet.

Ok, let’s start drawing. Click the Rectangle tool from the tool box on the left-hand side of the screen and draw it into the preview window, making sure you leave a bit of blank space round the edges. In the top-left corner of the rectangle there are two anchor points which you can drag in order to round-off the corners.

The rounding effect is specified by the RadiusX and RadiusY properties in the Appearance category so as you drag the anchor points they will both change automatically. The alternative, of course, is to type the values in manually.

When you’re happy with the roundness of your corners select a nice garish red colour for the background, and keep the Stroke, (outline), colour as Black.

This is the Rectangle we will change the colour of in our application, so we also need to give it a name to refer to later. At the top of the property pane change the Name property from “<No Name>” to “btnBG”.

Excellent! Now it’s time to get all arty and create the glass effect using gradients. Aesthetically, this section of the tutorial is completely up to you as long as you follow a few basic rules; but we’ll get to them in a sec.

Copy and paste the rectangle you’ve just created, change the Stroke alpha to 0%, and select Gradient as the fill type.

You can add colours to the gradient by clicking on the gradient bar underneath the colour square, and then dragging them along to edit the transitions between them. Just make sure you only use White and Black so we don’t end up with a button that looks strange when we change its background colour later. Each colour you add can have independent alpha values for transparency.

I made a gradient going from semi-transparent Black, to fully-transparent White, and then reduced the Rectangle’s overall Opacity to 77%.

Now let’s create a layer to give the button a highlight. Copy and paste the last rectangle you made and edit the gradient again. Then fade it out a lot more using the Opacity slider and alpha values.

Don’t worry if it doesn’t look that great. The secret to being a good graphic designer is to assume that everything you do is brilliant no matter how bad it actually looks.

When you’re happy with your button hit CTRL+S to save the project and then go back to Visual Studio. You should be confronted with a message box telling you that some of the project files have changed and asking if you would like to reload them. Just click “Yes”, and we’re ready for some programming.

3. Creating and Reading Cookies using ASP

I won’t go into too much detail about Cookies here because we’d be digressing from the main topic too much. All we need to do is create three Cookies that store colour information. This will be the colour Silverlight will use for our button Control. We’ll also create three text boxes in a moment so we can specify which one we want for our application. For the purposes of this demonstration, we'll set the cookies to be ephemeral. We'll set the expiry to be tomorrow. If you were doing it for real, you'd want something a lot more permanent!

Rename “TestPage.html” to “TestPage.asp” and add the following lines of code above the <html> tag:

<%

Dim r, g, b

Dim r2, g2, b2

 

response.cookies("BtnColorR").Expires=date+1

response.cookies("BtnColorG").Expires=date+1

response.cookies("BtnColorB").Expires=date+1

 

r2 = Request.QueryString("rIn")

g2 = Request.QueryString("gIn")

b2 = Request.QueryString("bIn")

 

if r2 <> "" and g2 <> "" and b2 <> "" then

 response.cookies("BtnColorR")=r2

 response.cookies("BtnColorG")=g2

 response.cookies("BtnColorB")=b2

end if

 

r=request.cookies("BtnColorR")

g=request.cookies("BtnColorG")

b=request.cookies("BtnColorB")

 

if r="" or g="" or b="" then

   response.cookies("BtnColorR")=0

   response.cookies("BtnColorG")=0

   response.cookies("BtnColorB")=0

   r=0

   g=0=0=0=0

   b=0

end if

%>

When that’s done, save the file.

4. Creating and populating Form elements using ASP

Again, this is quite simple. We just need to create a standard HTML form with three text boxes, one submit button, and three hidden form elements.

Open “TestPage.asp” again, and add these lines of code within the <body> tags:

    <form action="TestPage.asp">

   

      <input type="text" name="rIn" value="<%=r%>">

      <input type="hidden" id="r" value="<%=r%>">

   

      <input type="text" name="gIn"  value="<%=g%>">

      <input type="hidden" id="g" value="<%=g%>">

   

      <input type="text" name="bIn"  value="<%=b%>">

      <input type="hidden" id="b" value="<%=b%>">

 

<input type="submit" value="Save Colour">

 

    </form>

Save the file, and we’re done with Cookies.

The hidden form elements will be the ones our application reads when it loads to get the colour for the button. The text boxes will allow us to specify which colour values we want, and they’ll be saved to our Cookies when the user hits the submit button.

5. Creating our User Control button object at run-time

This is actually a very similar process to the one we used for our High-Speed Loop in my previous article, so if you get lost here you should probably read through that one before continuing.

In order to create our button object, we first declare a variable using the New keyword. Open “Page.xaml.vb” and add the following line:

    Dim btnControl As New button

The button type is a direct reference to our “button.xaml” file. If you called your User Control something other than “button.xaml”, you’ll have to change this accordingly.

We then need to set up a variable to point to our main Canvas object.

    Dim pCanvas As Canvas

Now we have our variables, we need to alter the Page_Loaded function to add our button to the Canvas when the application loads. Find the Page_Loaded function and add the following highlighted lines of code:

    Public Sub Page_Loaded(ByVal o As Object, ByVal e As EventArgs)

        ' Required to initialize variables

        InitializeComponent()

 

 

        ' set pCanvas to our root canvas object

        pCanvas = FindName("parentCanvas")

 

        ' add our control to the canvas

        pCanvas.Children.Add(btnControl)

 

    End Sub

Once that’s done, save the file.

6. Changing parameters for our UI object

We’ve already covered updating Silverlight object parameters in the previous two articles, so I’ll try to avoid repeating myself again. All we need to do is set the colour parameter for the button UI object we created in Expression Blend. To do this, we’ll create sub-routines within the button object so we don’t clutter up the main section of code for the application.

Expand “button.xaml” in the Solution Explorer, if it isn’t already, and then open “button.xaml.vb”. Then add a variable we can use to point to our background rectangle.

    Dim bg As Rectangle

We’ll also need three Byte variables to store the colour the button should be:

    Public r, g, b As Byte

Next, let’s write a sub routine that does our colour changing. The Colour change method we’ll create will take 4 byte values and use them to change the Rectangle.FillProperty value of bg.

    Private Sub ChangeBG(ByVal a As Byte, ByVal r As Byte, ByVal g As Byte, ByVal b As Byte)

 

        bg.SetValue(Rectangle.FillProperty, Color.FromArgb(a, r, g, b))

 

    End Sub

We’ve made this sub routine public so we can call it from “Page.xaml” later.

To create a MouseOver event, to apply our colour change, let’s create two new functions. The first one is called mOver, and the second is called mOut.

    Private Sub mOver(ByVal o As Object, ByVal e As EventArgs)

 

        ' change the fill colour of the BG rectangle

        ChangeBG(255, r, g, b)

 

    End Sub

 

    Private Sub mOut(ByVal o As Object, ByVal e As EventArgs)

 

        ' change the fill colour of the BG rectangle

        ChangeBG(255, 0, 0, 0)

 

    End Sub

mOverchanges the colour of our button to the values of our r, g, and b variables. mOut returns it to Black when the mouse leaves the button.

Something to watch out for when developing Silverlight applications is the order in which functions are called. At certain points of the loading process you will find that some methods return an error, simply because the object you’re trying to reference doesn’t exist yet. The easiest way to get around this is to use the “Loaded” property on the object you want to work with, and use it to call a function that will only work when that object has been created.

Let’s create a sub routine that will point our bg variable to the rectangle we need to change the colour of, and then call our Colour change function to make our background rectangle Black when the application starts:

    Private Sub bgLoad(ByVal sender As Object, ByVal e As EventArgs)

 

        ' set bg to the rectangle that called this sub

        bg = sender

 

        ' change the fill colour of the BG rectangle

        ChangeBG(255, 0, 0, 0)

 

    End Sub

The sender parameter will point to the object that called this sub routine. In this case it will be the rectangle we want to change the colour of. For this to work, we now add a Loaded parameter to our rectangle in “button.xaml”.

Open “button.xaml” and find the first rectangle tag inside the Canvas tags. Then add the following highlighted segment of code:

<Rectangle Loaded="bgLoad" Width="234" Height="84" Fill="#FFFF0000" Stroke="#FF000000" Canvas.Left="8" Canvas.Top="8" RadiusY="11.5" RadiusX="11.5" Opacity="1" x:Name="btnBG" StrokeThickness="1"/>

Now find the last rectangle tag in the Canvas and add the following highlighted bit of code:

  <Rectangle MouseEnter="mOver" MouseLeave="mOut"  Opacity="0.51" Width="234" Height="84" Stroke="#00000000" RadiusX="11.5" RadiusY="11.5" Canvas.Left="8" Canvas.Top="8">

    <t;Rectangle.Fill>

      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

        <GradientStop Color="#FF000000" Offset="0"/>

        <GradientStop Color="#FFFFFFFF" Offset="0.174"/>

        <GradientStop Color="#00FFFFFF" Offset="1"/>

      </LinearGradientBrush>

    </Rectangle.Fill>

  </Rectangle>

Hit F5 and see what happens.

Your button should be displayed in the top-left hand corner of the application, and it should be Black! Move your Mouse cursor over the button and it will remain Black… for now.

7. Passing data from the Document to Silverlight

Now the button is being displayed, we just need to pass the data from our ASP page to Silverlight and we’re good to go.

Well… to be more precise, we’ll suck the data from the page using the HtmlDocument and HtmlElement objects from within Silverlight.

To do this we need to first Import the System.Windows.Browser namespace. So, open up “Page.xaml.vb” and add the following line to the very top of the file:

Imports System.Windows.Browser

Then we need to create a variable that will point to our application’s host document:

    Dim document As HtmlDocument

We nearly have full access to the document and all the elements within it. We only need three elements though: The Red, Green, and Blue hidden form elements we created earlier. Once we are able to access those we need to populate the public r, g, and b variables within our button.

Add the following highlighted lines of code to the Page_Loaded function:

    Public Sub Page_Loaded(ByVal o As Object, ByVal e As EventArgs)

        ' Required to initialize variables

        InitializeComponent()

 

 

        ' set pCanvas to our root canvas object

        pCanvas = FindName("parentCanvas")

 

        ' add our control to the canvas

        pCanvas.Children.Add(btnControl)

 

        document = HtmlPage.Document

 

        Dim rElement As HtmlElement = document.GetElementByID("r")

        Dim gElement As HtmlElement = document.GetElementByID("g")

        Dim bElement As HtmlElement = document.GetElementByID("b")

 

        btnControl.r = rElement.GetAttribute("value")

        btnControl.g = gElement.GetAttribute("value")

        btnControl.b = bElement.GetAttribute("value")

 

    End Sub

Setting the document variable to HtmlPage.Document opens up the host page for us to read through and get data from. For each of the three elements we’re interested in, (r, g, and b), we need to get the value attribute and populate our button’s r, g, and b variables.

Now, when you run the application, you will be able to specify and store the colour you want the button to change to when you move your mouse over it!

Summary

Changing the colour parameters for one button object is just the tip of an extremely large iceberg. Obviously, You could store all sorts of information, in various ways, and subsequently change any number of properties allowing your users to create their most comfortable working environment. Your users could have a field-day customising the entire look of the application; be it position, colour, or style.

Your application could well become your company’s equivalent to MySpace™; a veritable treasure-trove of elaborately awful design layouts.It’s completely up to them and, more importantly, you can’t be blamed for it!

More importantly, I hope I've shown how easy it is to use Expression Blend in the design of your application. Hopefully, there will be fewer hours spent obsessively moving buttons around the screen!

If you would like to see this project in action, go to:
http://www.deepspaceobjects.com/examples/skinnableUI/
...and all the source code, in both VB and C#, is in the speechbubble at the top of the article.

John Bower

Author profile:

John Bower spent six years as Lead Web Designer at FreshEgg before getting an MA in 3D Computer Animation at the National Centre of Computer Animation, UK. He is now running DeepSpaceObjects consultancy, specialising in Flash Development and has contributed to a number of celebrity and business websites.

Search for other articles by John Bower

Rate this article:   Avg rating: from a total of 13 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: UI for Dummys
Posted by: Larsonst (not signed in)
Posted on: Tuesday, February 12, 2008 at 3:38 PM
Message: I am all in favor of empowering the end user of anything, from cars to portal dashboards, HOWEVER, UI design is a profession and not an opinion.

One foundation for usable UI development is that no human being can anticipate how another will respond to a layout no matter how hard we try. Think about all of the efforts you have made in life to make it just right for someone else only to quickly have your erroneous assumptions revealed by "those who don't get it."

Excuse me, but anyone who has worked on the innards of a application has deep knowledge of how it works and is unqualified to design for the new user. This is why user testing using virgins is the only reliable method to verifying quality user interface design.

This widely ignored wisdom runs counter to "expert opinion" (e.g. programmers and project managers). Rather than avoiding this issue by shifting blame from one class (developers) and laying it on the most inexperienced person in the room (end users) why not promote user testing as the best approach to lowering training requirements and user input errors and supporting usability and functionality retention?

Subject: RE: UI for Dummys
Posted by: John Bower (not signed in)
Posted on: Tuesday, February 12, 2008 at 7:30 PM
Message: To a certain extent, I agree with Larsonst. I wouldn't recommend designing an application's UI to be 100% customizable. There's no point in offering end users a blank canvas to design their own UI for because, as you say, they are the most inexperienced to do so.

However, even a carefully constructed Windows application, with X number of years of UI research, could be totally ruined by someone who has messed about with the visual appearance of their operating system; let alone if they've installed something like Stardock's WindowBlinds. A Silverlight UI wouldn't be affected by software like that, so the ability to customize the application is entirely up to the developer.

User testing is always vitally important but why should you only offer them a closed UI that they can't personalise? Most operating systems allow this and it's a feature that's kept a lot of users amused for years.

If you were to include UI skinning to your application, it would make sense to allow them to alter a functional pre-designed layout within set boundries.

 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.