500 likes | 587 Views
Uncover the inner workings of Silverlight's controls skinning framework through usercontrols, styling, control templates, and the Parts and States Model. Learn how to build custom controls, utilize DependencyProperty, and enhance UI maintainability. Explore the power of ControlTemplates and the Visual State Manager for advanced control customization.
E N D
Under the hood in Silverlight’s controls skinning framework Gill Cleeren Microsoft Regional Director – MVP ASP.NETOrdina .NET Architect gill.cleeren@ordina.be
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: gill.cleeren@ordina.be • Twitter: gillcleeren • MSN: gillcleeren@hotmail.com
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 • 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 sidestep • Type 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 system • Not only for UserControls (ie. We’ll need it further in this talk!)
DependencyProperty public static readonlyDependencyPropertyIsLockedProperty = DependencyProperty.Register( "IsLocked", typeof(bool), typeof(LockableTextBox), new PropertyMetadata(new PropertyChangedCallback(OnIsLockedChanged)) ) public bool IsLocked { get { return (bool)(GetValue(IsLockedProperty)); } set { SetValue(IsLockedProperty, value); } } private static void OnIsLockedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { LockableTextBox textBox = (LockableTextBox)(o); textBox.UpdateUI(); }
Demo Building 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
Demo Styling 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 • 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
Demo ControlTemplate, 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
Demo A 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 DownRepeatButton Thumb UpRepeatButton Track • Named element in template: “working parts” • Not in every control • Code manipulates element in some way
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 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 { ... } • Visual look of control in a particular state
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 VisualTransition MouseOver Pressed • Visual look of control as it goes between states • Reverts automatically
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"> <LinearDoubleKeyFrameKeyTime="0:0:0.5" Value="0" /> <LinearDoubleKeyFrameKeyTime="0:0:0.7" Value="1" /> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualTransition> </VisualStateGroup.Transitions>
Selecting The VisualTransition • Types 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
Demo Visual State Manager: Creating a new checkbox
Recap: VSM • ViewStateManager • VisualStateGroups • VisualStates • Transitions • Generated (not for object animations) • Specific
VisualStateManager from code-behind VisualStateManager GoToState() VisualStateGroups Defined in template Called in control code Not limited to XAML: more options in code-behind
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
Demo VSM from code-behind
VSM Code-behind take-aways • TemplatePart & TemplateVisualState • GoToState • OnApplyTemplate
Demo VSM 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...?
Thank you Under the hood in Silverlight’s controls skinning framework Gill Cleeren Microsoft Regional Director – MVP ASP.NETOrdina .NET Architect gill.cleeren@ordina.be