Zero to Hero: XAML from the ground up

del.icio.us Tags: Silverlight

 

Technorati Tags: Silverlight

  

 

In the last Episode, you looked into Getting Started with Silverlight where you had a simple XAML document containing a TextBlock that you then manipulated in code.

XAML is at the heart of Silverlight. You use it to define your user interface layout, interactions, animations and more. It's very simple to use, but at first it may look a little daunting.

XAML is just XML, so it's pretty easy to use and understand. If you don't know XML, some of the terms such as 'element', 'attribute' and 'child' that I'll be using may be a little alien to you -- in that case I strongly recommend a quick visit to one of my favorite sites on the net: w3cschools.com.

There are a number of different element types in XAML: Shapes for basic UI drawing, Controls for more complex functionality, Geometries for manipulating objects and Layout elements to control your UI.

Many of these have a number of attributes in common with each other, so I'm going to start with the most common ones that you might encounter, and when you understand how they apply to one element, the same will apply to all elements.

Layout Properties

Laying XAML Elements out in a scene is achieved using the Canvas.Left and Canvas.Top attributes. These are simply the number of pixels that your element will appear from the left and from the top of its container. Note that I say container, and not screen, as the <Canvas> element can contain other canvas elements and their children will be placed relative to them. In addition to this, element have a Canvas.ZIndex property that is used to add a (sort-of) third dimension, allowing you to place elements on top of each other.

So, here is a piece of XAML that lays two rectangles out within a canvas, with the first having its upper left hand corner at (8,8) and the second having its upper left hand corner at (20,20).

    1: <Canvas>
    2:     <Rectangle Fill="Red" Width="100" Height="100" 
    3:               Canvas.Left="8" Canvas.Top="8"/>
    4:     <Rectangle Fill="Black" Width="200" Height="80" 
    5:              Canvas.Left="20" Canvas.Top="20"/>
    6: </Canvas>

 

Simple, right? Note that Silverlight draws objects in the order that it reads them, so the red rectangle will be drawn first, followed by the black one. Yes, I know the red one is technically a square as it has the same height and width, but you'll forgive me for still calling it a rectangle! :)

 

Brush Properties

You saw in the previous section that our rectangles were painted red and black respectively. They were painted using Brushes, and properties such as Fill and Stroke take a brush as their content. To put it simply Fill dictates how an object is painted and Stroke dictates how it is outlined.

There are lots of brushes that you can use to paint an objects Fill or Stroke, including:

  • SolidColorBrush: Paints with a solid color, named (i.e. 'Red') or declared in RGB or ARGB hex (i.e. #FFFF0000)
  • LinearGradientBrush: Paints with a linear gradient that fades from one color to the next through a bunch of gradient stops
  • RadialGradientBrush: Paints with a radial gradient that fades from one color to the next through a bunch of gradient stops. Think of it as an ellipse that fades from one color at the center to another at the circumference
  • ImageBrush: Paints the surface with an image
  • VideoBrush: Paints the surface with video
  • BasilBrush: Paints the surface with a well dressed puppet fox

There's a lot more detail on these brushes in the Silverlight quickstarts here for the first four and here for the video brush, and of course here for the BasilBrush.

 

Visual Properties

The visual properties of your element are set with the attributes that you'd expect:

  • Width: In pixels
  • Height: In pixels
  • Opacity: 0 for transparent, 1 for opaque. So 0.5 would be semi-transparent
  • Cursor: Arrow, Default, Hand, IBeam, Wait or None (which is great for pranks, but the tech support people might kill you)

 

Shapes

XAML UI is made up of some pretty basic shapes. The ones that are available to you are:

  • Ellipse: An ellipse with height and width (make them the same for a circle)
  • Rectangle: A straight-edge four sided polygon with width and height
  • Line: A line between 2 defined points
  • Path: A series of connected points (a bit like a scribble)
  • Polygon: A straight edge many sided shape
  • Polyline: A series of connected lines

Wherever possible consitency is key, so, for example, the Ellipse and Rectangle have 'Height' and 'Width' properties, whereas sometimes you might think that the Ellipse would have 'RadiusX' and 'RadiusY' properties.

A great tutorial on using these can be found in the Silverlight quickstarts.

Controls

Silverlight 1.0 has a few Basic controls that provide specific functionality. They are:

  • Canvas: A Basic container, used for layout. More here.
  • Image: For rendering graphics. More here.
  • Glyphs: For rendering text characters. Useful for Unicode. More here.
  • TextBlock: For rendering text. More here.
  • MediaElement: For rendering sound and/or video. More here.

 

The XAML XSD

The XAML XSD is available in the Silverlight SDK. Mac Users who can not install the SDK can get it here.

It's a mightily useful document, once you know how to read it. Some people swear by XML visualization tools such as XML spy, but for me, there's nothing better than simple old notepad for viewing an XSD.

So, for example, if you want to know what the full property set of a <Rectangle> is, it's very simple. Open the doc and look for 'Rectangle'. You'll see something like this:

    1: <xs:element name="Rectangle" type="dRectangle"/>

You can see that Rectangles are of type 'dRectangle', so go take a look at dRectangle.

    1: <xs:complexType name="dRectangle">
    2:     <xs:choice minOccurs="0" maxOccurs="unbounded">
    3:       <xs:element name="Rectangle.Clip" type="dGeometryContainer" minOccurs="0" maxOccurs="1"/>
    4:       <xs:element name="Rectangle.RenderTransform" type="dTransformContainer" minOccurs="0" maxOccurs="1"/>
    5:       <xs:element name="Rectangle.Triggers" type="dTriggerCollectionContent" minOccurs="0" maxOccurs="1"/>
    6:       <xs:element name="Rectangle.OpacityMask" type="dBrushContainer" minOccurs="0" maxOccurs="1"/>
    7:       <xs:element name="Rectangle.Resources" type="dResourceDictionaryContent" minOccurs="0" maxOccurs="1"/>
    8:       <xs:element name="Rectangle.Fill" type="dBrushContainer" minOccurs="0" maxOccurs="1"/>
    9:       <xs:element name="Rectangle.Stroke" type="dBrushContainer" minOccurs="0" maxOccurs="1"/>
   10:     </xs:choice>
   11:     <xs:attribute name="Name" type="StringToStringConverter"/>
   12:     <xs:attribute name="Opacity" type="StringToDoubleConverter"/>
   13:     <xs:attribute name="Clip" type="StringToGeometryConverter"/>
   14:     <xs:attribute name="RenderTransform" type="StringToTransformConverter"/>
   15:     <xs:attribute name="Triggers" type="StringToTriggerCollectionConverter"/>
   16:     <xs:attribute name="Canvas.Left" type="StringToDoubleConverter"/>
   17:     <xs:attribute name="Canvas.Top" type="StringToDoubleConverter"/>
   18:     <xs:attribute name="Canvas.ZIndex" type="StringToInt32Converter"/>
   19:     <xs:attribute name="OpacityMask" type="StringToBrushConverter"/>
   20:     <xs:attribute name="Loaded" type="StringToStringConverter"/>
   21:     <xs:attribute name="MouseMove" type="StringToStringConverter"/>
   22:     <xs:attribute name="MouseEnter" type="StringToStringConverter"/>
   23:     <xs:attribute name="MouseLeave" type="StringToStringConverter"/>
   24:     <xs:attribute name="MouseLeftButtonDown" type="StringToStringConverter"/>
   25:     <xs:attribute name="MouseLeftButtonUp" type="StringToStringConverter"/>
   26:     <xs:attribute name="KeyUp" type="StringToStringConverter"/>
   27:     <xs:attribute name="KeyDown" type="StringToStringConverter"/>
   28:     <xs:attribute name="GotFocus" type="StringToStringConverter"/>
   29:     <xs:attribute name="LostFocus" type="StringToStringConverter"/>
   30:     <xs:attribute name="RenderTransformOrigin" type="StringToPointConverter"/>
   31:     <xs:attribute name="Cursor" type="StringToCursorsConverter"/>
   32:     <xs:attribute name="IsHitTestVisible" type="StringToBooleanConverter"/>
   33:     <xs:attribute name="Visibility" type="StringToVisibilityConverter"/>
   34:     <xs:attribute name="Resources" type="StringToResourceDictionaryConverter"/>
   35:     <xs:attribute name="Tag" type="StringToStringConverter"/>
   36:     <xs:attribute name="Width" type="StringToDoubleConverter"/>
   37:     <xs:attribute name="Height" type="StringToDoubleConverter"/>
   38:     <xs:attribute name="Fill" type="StringToBrushConverter"/>
   39:     <xs:attribute name="Stroke" type="StringToBrushConverter"/>
   40:     <xs:attribute name="StrokeMiterLimit" type="StringToDoubleConverter"/>
   41:     <xs:attribute name="StrokeThickness" type="StringToDoubleConverter"/>
   42:     <xs:attribute name="StrokeStartLineCap" type="StringToPenLineCapConverter"/>
   43:     <xs:attribute name="StrokeEndLineCap" type="StringToPenLineCapConverter"/>
   44:     <xs:attribute name="StrokeLineJoin" type="StringToPenLineJoinConverter"/>
   45:     <xs:attribute name="StrokeDashOffset" type="StringToDoubleConverter"/>
   46:     <xs:attribute name="StrokeDashCap" type="StringToPenLineCapConverter"/>
   47:     <xs:attribute name="StrokeDashArray" type="StringToDoublesConverter"/>
   48:     <xs:attribute name="Stretch" type="StringToStretchConverter"/>
   49:     <xs:attribute name="RadiusX" type="StringToDoubleConverter"/>
   50:     <xs:attribute name="RadiusY" type="StringToDoubleConverter"/>
   51:   </xs:complexType>

Badda-Bing! You can now see everything that the Rectangle supports, and the type, which you can also look up in the XSD. Neat right?

 

Help Files and Documentation

The Silverlight.chm file installs as part of the Silverlight SDK. This is a phenomenally useful piece of software. If you haven't installed the SDK, you can still see all the contents here

So, Silverlight Mac users, rejoice, you can now access all the docs. Maybe I'll even figure out how to integrate them into Aptana in a future installment of zero to hero :)

XAML Tools

Finally, now that you know what's going on with XAML, there are tools beyond notepad that you can use.

Expression Design: This is a graphical design tool that can express (hence the name) your work as XAML. It has a free trial download.

Expression Blend: This is an interface design tool, complete with Silverlight templates that you can use to build XAML-centric experiences. It, too, has a free trial download.

SilverlightPad: A Silverlight Application that is a Silverlight creation tool. A very cool tool by the always cool Mike Harsh.

 

Silverlight Book

By the way, I'll be going into a lot more detail on these in my Silverlight Book with all the proceeds going to the Laurence Moroney XBox addiction fund.