This is the third in a four part series on understanding Silverlight by a Flex developer.
Links
Act III: Encounter
In this Act, we delve into styling, control templates and state management in Silverlight. All of the features we’ll cover are XAML related, and as such, can be managed completely within Blend.
Markup Extensions
Those curly braces in XAML are actually “markup extensions”, used for more than just data binding. Essentially, they allow a linking of one property to its value elsewhere. Resources - including styles and templates - are set using the markup extension syntax, and also provide compiler-level checking.
In Flex, we use data binding (and hence the curly brace syntax) to add any code to our MXML. The compiler attempts to make a data binding association, even if we didn’t actually want one. In Silverlight, the association is simpler. The XAML parser reads the extension as an indication that the property is defined (and perhaps bound) elsewhere.
Examples: Different markup within extensions in Silverlight
- Static Resources (see Resources, below)
<Button Style="{StaticResource MyButtonStyle}" ... />
- Template Bindings (see Control Templates, below)
<Border Padding="{TemplateBinding Padding}" ... />
- Nulls
<StackPanel Background="{x:Null}" ... />
- Data Bindings (basic syntax - see Act IV)
<TextBox Text="{Binding FirstName}" ... />
Markup extensions are more extensive in WPF, allowing for dynamic resources, static values and even the facility to create custom ones.
Unlike Flex, markup extensions are strict and do not allow the insertion of code in any form.
i.e. this shortcut in Flex,
<mx:Text alpha="{someValue * 0.5}" />
would not be valid in Silverlight:
Resources
Silverlight (and WPF for that matter) centrally manages its resources for each control. Unlike resource bundles in Flex, typically localisation and media repositories, resources in Silverlight are more like reusable XAML structures. These include:
- styles
- brushes
- graphics primitives
- storyboards
- control templates (which is like a skin in Flex 4)
Unlike WPF, resources in Silverlight 3 are cached and are static, meaning they can’t be changed at runtime.
Until recently, resources had to be embedded within the XAML of either one of the controls, or the application itself. Silverlight 3 has overcome this issue with merged dictionaries (external resource files).
Ex 1: Using Merged dictionaries in Silverlight 3 (MyBrushes.xaml)
MainPage.xaml
More Info
Content Controls
How well do you know the humble BUTTON tag in HTML? You know how you can insert other markup inside it? Well, that - in essence - is what a content control in Silverlight is. If you want, you throw some text inside a property; if you want more detail, you simply define the content. This is somewhat similar to using the Component tag for inline itemRenderers in Flex.
Ex 2: Quick content control example (use Tab Control example)
Styling
As we know, Flex uses a variant of Cascading Style Sheets (CSS), lowering the bar to entry for HTML devs. Flex 4 has taken this to the next level, implementing even more useful css selector syntax. Silverlight on the other hand, doesn’t use CSS. Instead, its styling solution lives within the XAML. In its simplest form, styling is simply a collection of property setters. It differs from Flex as these setters may be objects themselves that can be styled separately again - satiating your recursive compulsion.
You can style a component inline, just as you can in Flex, though if you want to reuse them, you store the style setters as resources.
Ex 3: Styling a button with a reusable style
The above example wasn’t produced by hand. Blend provided the tools that allowed me to visually style the button and have the results outputted in XAML. By selecting Object > Edit Style > Create Empty after you’ve placed an object onto the stage, you can modify the visual elements of the object, and it will be propagated to your style resource. Blend shows you a little palette icon in the breadcrumbs indicating that you are editing a style.
This is the same sort of functionality we are starting to see with Flash Catalyst. The difference is that Blend files this styling as a resource, allowing them to be reused - not unlike the “Convert to CSS” feature in the design mode of Flex/Flash Builder.
Silverlight 2 had the unfortunate vice of restricting the setting of styles at runtime once only. Thankfully, this restriction has been lifted in version 3. You can set a component’s style in the code-behind (using the Style property).
Silverlight 3 has also just implemented style inheritance via the BasedOn property.
Eg. Style Inheritance in Silverlight 3. Two buttons, the first is bold with a blue background and a hand cursor. The second, extends its style from that, and overrides the background to red.
Control Templates
Further to styling, Silverlight has an interesting feature known as Control Templates. These templates expose the view of Silverlight controls to the developer for easy modification. Flex 4 has compensated for these with a better skinning model. These two solutions are somewhat analogous, and help designers work on the aesthetics of controls independently to developers.
Ex 3: Simple boring button using template (MainPage.xaml). Here I’ve made a button render as a static bordered bit of text.
So far, what we have is pretty useless. At the very least, we need the text from the actual Button, rather than the static “Dare Me” text. Gumbo uses the HostComponent metadata tag in the skin to specify the component that is being skinned.
Ex 4: Basic button skin in Flex 4 (without the parts or states) (MyButtonSkin.mxml)
Whereas in Silverlight, they use the ContentPresenter tag, to allow the insertion of UI content. The TargetType property, set in the Control Template (and in Styles too, incidentally), tells the template, which control it is setting.
Ex 4: Using ContentPresenter in Silverlight (MainPage.xaml)
Now the button’s template is retrieved from the resource, and the content provided is automagically inserted into it.
Note: The ContentPresenter is for Content Controls specifically, and as such allows for any UI control, not just text.
Finally, the Control Template can easily overwrite the settings on your original control. For example, if we set the Button above to have a Padding of 50, we wouldn’t see a change. This is because the padding we set should be allocated into the Border control of the template, but Silverlight has no way of knowing this unless we explicitly specify it. To achieve this task, use a TemplateBinding.
Ex 5: TemplateBindings in Silverlight (XAML)
More on Control Templates:
Visual State Management
Note: Silverlight supports states via the Visual State Manger (or the VSM); WPF does not and instead uses a triggering event system. As such, a similar solution in the two frameworks would be created quite differently.
At first glance, Silverlight’s take on state management seems like the Flex model. Dig a little deeper however, and you’ll find some major holes in this assumption.
In principle, states and transitions in Silverlight perform the same function as they do in Flex 4. That is, a state is essentially a collection of property setters, effecting view elements, whilst transitions are the animations that guide the movement between the states. Actually, all states in Silverlight are essentially storyboards that run transitions either instantly or over a period of time, applying properties to componentry.
Unlike Flex, Silverlight allows for collapsed visibility on all components. This is essentially like setting display = none in the HTML/CSS world. If you need the object to become invisible (like visible = false in Flex), you set the opacity to 0. The advantage over Flex is that removing an object from rendering in a Silverlight state, is just another property setting:
For example, in Flex 3, we’d be used to the following:
In Flex 4, we can put the onus on the control:
In Silverlight, it’s just another property setter, albeit within an instantaneous transition animation.
Ex 6: An example Visual State in Silverlight. On the change to the Normal state, a storyboard is played in 10ms (effectively instantaneously) that hides an object - in this case a rectangle - from the application (this was created via the Blend tooling).
In Flex 3, when we wanted states to share settings, we’d inherit one from the other. For Flex 4, we use state groups to handle common settings. In the case of a Checkbox, we need to handle the typical button states of up, over, down and disabled, but then we need another 4 for the permutations with the selected state.
Ex 6: States of a Checkbox skin in Flex 4. Taken from the default spark Checkbox skin.
It's a much better solution than Flex 3, but still not fantastic, as we still have eight states to represent two distinct groups - one of four (up, over, down and disabled) and the other of two (selected, notSelected).
Silverlight instead uses its interpretation of state groups to prevent this scenario from occurring. Don't be fooled by thinking state groups are the same in Silverlight as in Gumbo - the difference is marked.
A Checkbox in Silverlight has four visual state groups, each with their own states:
- CommonStates
- Normal
- MouseOver
- Pressed
- Disabled
- CheckStates
- Unchecked
- Checked
- Indeterminate
- FocusStates
- Unfocused
- Focused
- ValidationStates
- Valid
- InvalidUnfocused
- InvalidFocused
As you can see, Silverlight also uses these state groups to handle validation and focusing, something we Flex developers typically leave to the framework. That said Flex 4 has now put the skinning of invalidation errors into components with the errorSkin property on components (spark.skins.default.ErrorSkin).
The deal with the state groups in Silverlight is that only one state of each may be active at one time. The obvious question is, what if two states, from different groups, try setting the same property to a different value? Basically, Blend will tell you off. In fact, you are discouraged from sharing controls across state groups.
Just with styles and templates, Blend will be your best friend when you want to fiddle with states and transitions - it’s a lot more capable than both Flash Builder and Catalyst are currently.
Ex 7: An overview of the states of a Checkbox
This is an abbreviated version of Silverlight’s template for the Checkbox control. You can find the whole version simply by adding a Checkbox to the stage in Blend, then selecting the breadcrumb, select Edit Template, then Edit a Copy.
If we have a look briefly at the group CheckStates, we can see the following:
Ex 8: CheckStates state group from default Checkbox template
See how, in the above example, each state is composed of a storyboard that sets properties in the template (the target controls are not shown for brevity):
- The Checked state sets the CheckIcon’s opacity to 1
- The Unchecked state does nothing
- The Indeterminate state sets the InderminateIcon’s opacity to 1
Now, as for changing the current state in the code-behind, we call a static method in the VisualStateManager class (C#):
Whereas we’d obviously do the following in Flex (AS3):
MyControl.currentState = "MyStateName";
Interestingly, states names here are simply strings like they are in Flex rather than object references; this has always been a bugbear of mine. Anyone have any suggestions as to why?
More on styling, templates and states:
Journal Notes
We've covered a lot of a control's front-end development in this Act.
- Markup Extensions
Markup extensions allow for property associations and data binding within XAML. Don’t be fooled by the syntax however - unlike Flex, the curly braces don't try to create a data binding association unless explicitly called for.
- Resources
Unlike Flex, resources in Silverlight are used to store commonly used data structures, such as styles, brushes, control templates and animations. Unfortunately, resources are cached at startup, meaning you cannot change them at runtime.
- Content Controls
These controls allow developers to exchange simple text, such as a button's label, with a completely new, fully customised, control - all inline within the markup.
- Styling
Styling uses XAML constructs rather than CSS to style. Whilst this makes editing the XAML by hand harder, it allows a lot of control in Blend. Styles are typically placed as resources for reusability.
- Control Templates
Templates are the Silverlight equivalent to Flex skins. They allow developers and designers to modify the entire appearance of Silverlight controls - including the built-in Silverlight components.
- State Management
Just like Flex, states allow a component to change its appearance at runtime to a predefined set of property setters affecting the template (or skin in Flexes case). Unlike Flex, Silverlight uses smart state grouping to prevent the creation of redundant code.
Get ready for the final Act, where we'll look more at back-end development, including data binding, dependency properties, attached properties and a few technical features that Silverlight alone offers. We’ve saved the best for last.