under the hood in silverlight’s controls skinning framework
DESCRIPTION
Under the hood in Silverlight’s controls skinning framework. Gill Cleeren Microsoft Regional Director – MVP ASP.NET Ordina .NET Architect [email protected]. About Gill. .net architect Ordina (ordina.be) Microsoft Regional Director (theregion.com) MVP ASP.net Writing: .net magazine - PowerPoint PPT PresentationTRANSCRIPT
Under the hood in Silverlight’s controls skinning frameworkGill CleerenMicrosoft Regional Director – MVP ASP.NETOrdina .NET [email protected]
About Gill• .net architect Ordina (ordina.be) • Microsoft Regional Director (theregion.com) • MVP ASP.net• Writing:
• .net magazine• Blogs • MSDN
• Speaking: • TechDays• Usergroups(Visug, Biwug, Besug)• Ineta speaker
• Blog: www.snowball.be • Email: [email protected]• Twitter: gillcleeren • MSN: [email protected]
Agenda It’s all about being in control• Usercontrols• Demo
• Controls with “Style”• Demo
Agenda It’s all about being in control• Skinning controls• Control templates
• Demo: the Round Button• A control from scratch
• Demo• Parts and states model and the Visual State
Manager• Demo
• In control of states from code-behind• Demo
• VSM loves Blend• Demo
UserControl: the easy-cheesy one
UserControl: the easy-cheesy one• Organize small portions of UI in more
manageable components• Fixed look with some logic• Split large XAML blocks into smaller parts• Reuse xaml/logic in multiple places, even
other projects• Similar to ASP.NET usercontrols• 3 step process:• Define appearance• Define behavior• Call the control
UserControl: the easy-cheesy one• Platform Support• <UserControl x:Class=“MyControl”> …
</>• public partial class MyControl :
UserControl {}• XAML is optional• DependencyProperty use is advised
DependencyProperty: a sidestepType of property that can be used with
DataBinding, Styling, Animations...Its value can rely on one or more sources
(StoryBoard, Binding...)2 step process to create a DP• Define the property• Register the property with the Dependency
systemNot only for UserControls (ie. We’ll need it
further in this talk!)
DependencyProperty
public bool IsLocked{ get { return (bool)(GetValue(IsLockedProperty)); } set { SetValue(IsLockedProperty, value); }}
public static readonly DependencyProperty IsLockedProperty = DependencyProperty.Register( "IsLocked", typeof(bool), typeof(LockableTextBox), new PropertyMetadata(new PropertyChangedCallback(OnIsLockedChanged)) )
private static void OnIsLockedChanged(DependencyObject o,DependencyPropertyChangedEventArgs e){ LockableTextBox textBox = (LockableTextBox)(o); textBox.UpdateUI();}
DemoBuilding and using a usercontrol:
a Lockable TextBox
Usercontrols take-aways• Bundle UI + behavior• Easy reuse• Split large files (XAML/C#)• Similar to ASP.NET
Controls with “Style”: the handy one• Share property values across multiple
elements• Similar to CSS• Needed to avoid maintenance nightmare• Implemented as “Style” property with
Setters collection• Available on FrameworkElement• No “Based-on” and “Default styles” at
this point, sadly
DemoStyling controls:
A small form with “Style”
Styling take-aways• Only change UI properties• Bundled and located in one place• Increases maintainability
Skinning controls: the powerful one
Skinning controls: the powerful one• Styling is somewhat limited• A template allows for complete
flexibility without losing functionality of the control
ControlTemplates & Co• Every control exposes a Template
property (of ControlTemplate type)• Gives you a clean slate to start from• Possible to have data binding
between Control and ControlTemplate using TemplateBinding
• Also possible to instruct Silverlight where to put the content using ContentPresenter
DemoControlTemplate, TemplateBinding and
ContentPresenter:“I’ve had it with those rectangle buttons...”
Control template take-aways• Swap in new visual tree for a control• TemplateBindings • ContentPresenter
Taking it a step further: a custom control from scratch• The "Built-in" Look• generic.xaml• Assembly resource in controls dll• Contains resource dictionary with built-in
styles• DefaultStyleKey• Value is the Type of control• Indicates which generic.xaml & which style in
that generic.xaml
DemoA complete custom control:
A not-so-good-looking start
Trouble in paradise• A: “Question: My control can only be
normal?”• B: “Good question! Custom control
doesn’t provide ability to create a “Clicked”, “MouseOver”... State”
• A: • B: “You need the Parts and States
Model”• A:
Introducing...• Parts and state model• Parts• States
• Where to get the states?• MSDN• Reflection
The Parts and States Model (PSM)• Goals• How to structure your control• Defined separation between logic & visuals• Explicit control contract
• Recommended pattern• Not enforced by runtime• Will be supported by Blend
The Parts and States Model (PSM) and the Visual State Manager• VSM relies on variety of components:
the PSM• Ensures clean separation between
visuals and logic• VSM is used to manage change
between states:• State-based effect (larger button when
mouse-over)• Transitioning effect (from mouse-over to
normal)
PSM: the Parts• Named element in template:
“working parts”• Not in every control• Code manipulates element in some
way DownRepeatButton
UpRepeatButton
Thumb
Track
The parts of the slider control
[TemplatePart(Name="HorizontalTemplate", Type=typeof(FrameworkElement))][TemplatePart(Name="HorizontalTrackLargeChangeIncreaseRepeatButton",Type=typeof(RepeatButton))][TemplatePart(Name="HorizontalTrackLargeChangeDecreaseRepeatButton",Type=typeof(RepeatButton))][TemplatePart(Name="HorizontalThumb", Type=typeof(Thumb))][TemplatePart(Name="VerticalTemplate", Type=typeof(FrameworkElement))][TemplatePart(Name="VerticalTrackLargeChangeIncreaseRepeatButton",Type=typeof(RepeatButton))][TemplatePart(Name="VerticalTrackLargeChangeDecreaseRepeatButton",Type=typeof(RepeatButton))][TemplatePart(Name="VerticalThumb", Type=typeof(Thumb))]...public class Slider : RangeBase{ ... }
PSM: the States• Visual look of control in a particular
state
MouseOver Pressed
[TemplateVisualState(Name="Normal", GroupName="CommonStates")][TemplateVisualState(Name="MouseOver", GroupName="CommonStates")][TemplateVisualState(Name="Pressed", GroupName="CommonStates")][TemplateVisualState(Name="Disabled", GroupName="CommonStates")][TemplateVisualState(Name="Unfocused", GroupName="FocusStates")][TemplateVisualState(Name="Focused", GroupName="FocusStates")]public class Button : ButtonBase{ ... }
PSM: the State Group• Set of mutually exclusive states• Different state groups are orthogonal
State groups for Button<ControlTemplate x:Key="ButtonTemplate" TargetType="Button"> <Grid> <VisualStateManager.VisualStateGroups> ... </VisualStateManager.VisualStateGroups> <Border x:Name="ButtonBorder" BorderBrush="Orange"
BorderThickness="3“ CornerRadius="15"> <Border.Background> <SolidColorBrush x:Name="ButtonBackgroundBrush"
Color="Red" /> </Border.Background> <ContentPresenter ... /> </Border> </Grid> </ControlTemplate>
State groups for Button<ControlTemplate x:Key="ButtonTemplate" TargetType="Button"> <Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> ... </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> ... </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Border x:Name="ButtonBorder" BorderBrush="Orange"
BorderThickness="3" CornerRadius="15"> ... </Border> </Grid> </ControlTemplate>
State groups for Button<ControlTemplate x:Key="ButtonTemplate" TargetType="Button"> <Grid> <VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="MouseOver"> ... </VisualState> <VisualState x:Name="Normal"> ... </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> ... </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Border x:Name="ButtonBorder" BorderBrush="Orange"
BorderThickness="3“ CornerRadius="15"> ...
State groups for Button<ControlTemplate x:Key="ButtonTemplate" TargetType="Button"> <Grid> <VisualStateManager.VisualStateGroups> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="MouseOver"> <Storyboard> <ColorAnimation Duration="0:0:0“ Storyboard.TargetProperty="Color" To="Orange“ Storyboard.TargetName="ButtonBackgroundBrush“ /> </Storyboard> </VisualState> <VisualState x:Name="Normal"> ... </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates">...
PSM: the Transitions• Visual look of control as it goes
between states• Reverts automatically
MouseOverPressed
VisualTransition
PSM: the Transitions• VisualTransition class• Contains duration for automatic
transition animations
• Automatic Transition Animations• Generate linear transitions for
properties set in VisualState by Color, Point, & Double animations, not for Object animations
Transitions for the Button: Default transition<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0:0:0.2" /> </VisualStateGroup.Transitions> <VisualState x:Name="MouseOver"> <Storyboard> <ColorAnimation Duration="0:0:0"
Storyboard.TargetName="ButtonBackgroundBrush" Storyboard.TargetProperty="Color" To="Orange" />
</Storyboard> </VisualState> .....
Transitions for the Button:Specific transition<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup.Transitions> <VisualTransition To="MouseOver" GeneratedDuration="0:0:0.5" /> <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.1" /> </VisualStateGroup.Transitions> .....
Transitions for the Button:Custom transition<VisualStateGroup.Transitions> <VisualTransition To="Normal" From="MouseOver" GeneratedDuration="0:0:0.7"> <Storyboard> <DoubleAnimationUsingKeyFrames
Storyboard.TargetName="ScaleTransform"Storyboard.TargetProperty="ScaleX">
<LinearDoubleKeyFrame KeyTime="0:0:0.5" Value="0" /> <LinearDoubleKeyFrame KeyTime="0:0:0.7" Value="1" /> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualTransition> </VisualStateGroup.Transitions>
Selecting The VisualTransitionTypes of transitions: (MouseOver Pressed)• From/To
• <VisualTransition To=“Pressed” From=MouseOver” …>• To
• <VisualTransition To=“Pressed” … >• From
• <VisualTransition From=“MouseOver” … >• Default
• <VisualTransition …>
Selects most specific transition
DemoVisual State Manager:
Creating a new checkbox
Recap: VSM• ViewStateManager• VisualStateGroups• VisualStates• Transitions• Generated (not for object animations)• Specific
Visual State Manager from code-behindNot limited to XAML: more options in
code-behind
VisualStateManagerGoToState() VisualStateGroups
Called in control code
Defined in template
Visual State Manager from code-behind• Building blocks: • Control contract metadata• TemplatePart• TemplateVisualState
• NOT used by runtime. Leveraged by tools.• public static
VisualStateManager.GoToState()• Manages visual state change logic & transitions
• public override void OnApplyTemplate()• Called when new template has
been applied
DemoVSM from code-behind
VSM Code-behind take-aways• TemplatePart & TemplateVisualState• GoToState• OnApplyTemplate
DemoVSM in Blend
Summary• User controls: for combining controls
and easy reuse• Styling: for changing normal
properties on a scalable manner• Control template: allows for
overriding complete look and feel• Visual State Manager: extending the
control template to manage states
Resources• Scorbs.com• Silverlight in Action (Manning, 2008)• MSDN library
Q&A
Did you understand everything...?
Under the hood in Silverlight’s controls skinning frameworkGill CleerenMicrosoft Regional Director – MVP ASP.NETOrdina .NET [email protected]
Thank you