January 10, 2010

Silverlight Bits&Pieces: Controls Basics

Silverlight is all about controls, and I have yet barely touched them. It’s about time to change this.

And since controls are such an ingrained feature of SL, I can safely refer to others for the bread-and-butter explanations and focus on the key points afterwards. (Still, is post is going to be about fairly basic stuff.)

The basics…

Control Customization (MSDN) does a good job of naming the core concepts, namely Style, Template, Parts, States and State Groups.

Many Softies blogs about SL, I found Dan Wahlin particularly valuable (and he’ll point you to others.)

Actually this is how I started. Using controls the way I did in WinForms or ASP.NET, setting properties, layouting, styling. It is all so common and natural, I didn’t spend much thought on controls per se at first.

However, treating SL controls like WinForms controls doesn’t do them credit and neglects quite a bit of the potential. Actually, in my opinion, the SL control system is one step ahead of all previous systems.

And the glue holding this triumvirate together is the properties, more accurately dependency properties. The following image is an attempt to describe this relationship:

Controls define their properties, and only the properties defined in a control are accessible for manipulation via styles or to be referenced by templates.

Templates make up the shape of the control, by assembling Parts into a new compound representation.

And styles set property values that affect either the behavior or are referenced by the template to affect the appearance or content of a Part.

Add the fact that properties may be subject to databinding and you get a very concise system.

In More Detail…

Control…

SL controls come as classes (surprise!), but their job is only to define behavior (unlike WinForms or WebForms controls that also do the rendering). E.g. a button control essentially does three things:

It defines behavior. I.e. it reacts on mouse over and mouse click to render a hover effect or trigger the click event.

It defines (dependency) properties. The properties offer a way of controlling the behavior and appearance – if the control code or the template chose to refer to them.

It triggers the rendering process, deferring it to the template(s). Usually controls bring their own default template within the resources, many let the template be replaced either partly (usually by setting a Contentproperty), or completely by setting some Templateproperty.

Style…

Styles are essentially a way to set a couple of properties of a control. Period.

To be more elaborate, Styles don’t care whether those values actually style the control in the sense of designing it. For example I can set the selection mode of a data grid, which affects the behavior rather than the design. Styles can set virtually any property of any control, including the one I haven’t even written yet. Styles are also not restricted to certain (and in these cases typically simple) types; leveraging the power of XAML, styles can assign virtually any value of any type.

Lemma: Styles can only manipulate properties. Meaning if I need a button with an image I cannot simply set the image via a style, because the standard button control simply does not have a respective property. I need to derive a control and define a respective dependency property.

Since those properties are class specific, styles are consequently type specific (contrary to CSS), and have to unequivocally state that type. Hence one cannot define a style (say setting font type and size) and apply it to a textbox as well as to a link control. To one who is used to CSS this may come as a restriction.

Template…

Basically a template is the XAML representation of the Parts that together constitute the visual appearance of a control. This can be a mixture of primitives, but it could also incorporate other controls. Also there is some degree of “behavior” in the sense that this may include animations, visual state manager information, and other dynamic content. Depending on the control, a template can be partly set via some content property or completely via some template property. Some controls may offer more than one template, e.g. for header and cells in a data grid. Templates can refer to properties, by way of TemplateBinding, and those properties can afterwards be customized via styles.

Depending on the control (which carries the logic to “activate” them), templates can offer a wide spectrum of extensibility. As an example consider the following textbox, using an alternate template:

This template adds a small glyph to the textbox and sets its tooltip to the textbox content. And this is the result:

This is not bullet proof (changing the text won’t update the tooltip), but it should give a first hint on the potential of customization via templates.

Add visual state manager and states for mouse, selection, validation errors, put animations on top, and you get an unprecedented customizability of even the most basic controls. The down side is the unprecedented complexity, for example the template for the date picker control (extracted via blend) has about 150 LOC, and I have seen other with over 300 LOC.

Some Conventions…

SL controls don’t adhere to some global style, i.e. it is not possible to somehow state that every textbox should use a certain font within a given application (this is one of the new SL4 features, though). To make my default style assignments easier I like to have standard styles named after class (i.e. "Textbox” – not “DefaultTextbox” or “TextboxStyle”, or some other convention). One could replace the standard classes with derived classes or use some other generic mechanism, yet so far Blend and manual assignment worked fine for me.

Regarding templates, I generally don’t set the Template property within the page XAML. Rather I like to assign the template indirectly via a style. This way I won’t have to think about setting both properties, style and template, and worry about dependencies. Applied to the example above:

And the respective style which also sets the property:

If styles and templates are that powerful one could assume that the need to deriving controls was less prevalent. Matter of fact I do derive controls as often as before, only the reasons have changed: Mostly I derive controls to define properties that I need within custom templates and styles.

And I thought this might be a shorter post…. Anyway, the next post will lay out some additional basic stuff before I’m going to tackle derived controls and VSM.

Regarding the template question: I’ve been doing some work in this area for WP7 which might lead to a respective post. At the same time I’ve been extremely busy recently, so I cannot give any commitment, sorry.