Skinnable Custom Controls – Change to generic.xaml

This is the first in a series of explorations of breaking changes in the Release Candidate for Silverlight 2.  Please be sure to read Tim's blog entry about Silverlight RC0 for context and directions.


There are 2 significant breaking changes in how you handle the file generic.xaml when creating a Skinnable custom control in Silverlight 2.  This is a change from my blog post on 21st of September and the 12th of September and will be reflected in the forthcoming videos and tutorial.  The first change is that the file itself has a new location inside the Themes folder. The second is that the syntax has changed from declaring storyboards as resources and the referring to them in the declaration of Visual States, to combining the declaration of visual state with defining the associated storyboards.

The first change makes Silverlight more WPF-like.

The second change may or may not have been 100% intentional but will be in the release and I personally find it totally inoffensive.

Location, Location, Location

The file generic.xaml  has moved in RC0 from the root of the class library to a folder named Themes:


(Right click on Class Library and choose New Folder – name it Themes. Right click on the folder to choose New Item and create the user control or if you've already created it, drag it into the folder).


The syntactic change is to remove the <Grid.Resources> section and to combine the definition of the Storyboards with the definition of the States. Here is the old syntax:

   1: <ResourceDictionary
   2:  xmlns="" 
   3:     &lt;Style TargetType="controls:StatusControl">
   4:         <Setter Property="Template">
   5:             <Setter.Value>
   6:                 <ControlTemplate TargetType="controls:StatusControl">
   7:                     <Grid x:Name="LayoutRoot">
   8:                          <Grid.Resources>
   9:                             <Storyboard x:Key="MouseOverState">
  10:                             </Storyboard>
  11:                             <Storyboard x:Key="OnState">
  12:                             </Storyboard>
  13:                         </Grid.Resources>
  14:                         <vsm:VisualStateManager.VisualStateGroups>
  15:                             <vsm:VisualStateGroup x:Name="CommonStates">
  16:                                 <vsm:VisualState x:Name="Normal" />
  17:                                 <vsm:VisualState x:Name="MouseOver" 
  18:                                       Storyboard="{StaticResource MouseOverState }" />
  19:                             </vsm:VisualStateGroup>
  20:                             <vsm:VisualStateGroup x:Name="StatusStates" >
  21:                                       Storyboard="{StaticResource OnState }" />
  22:                             </vsm:VisualStateGroup>
  23:                         </vsm:VisualStateManager.VisualStateGroups>
  24:                         <Ellipse x:Name="Core" >
  25:                             <Ellipse.RenderTransform>
  26:                             </Ellipse.RenderTransform>
  27:                             <Ellipse.Fill>
  28:                             </Ellipse.Fill>
  29:                         </Ellipse>
  30:                     </Grid>
  31:                 </ControlTemplate>
  32:             </Setter.Value>
  33:         </Setter>
  34:     </Style>
  35: </ResourceDictionary>   





I've left out a lot of detail, but what is essential here is that we were declaring the storyboards as resources, and then referring to them in the VisualStateManager.VisualStateGroups.  The new syntax is to combine the Visual State declarations with their associated storyboards, as we do when creating templates:

   1: <ResourceDictionary
   2:     xmlns="" 
   3:     &lt;Style TargetType="controls:StatusControl">
   4:         <Setter Property="Template">
   5:             <Setter.Value>
   6:                 <ControlTemplate TargetType="controls:StatusControl">
   7:                     <Grid x:Name="LayoutRoot">
   8:                       <vsm:VisualStateManager.VisualStateGroups>
   9:                             <vsm:VisualStateGroup x:Name="CommonStates">
  10:                                 <vsm:VisualState x:Name="Normal" />
  11:                                 <vsm:VisualState x:Name="MouseOver" >
  12:                                     <Storyboard >
  13:                                     </Storyboard>
  14:                                 </vsm:VisualState>
  15:                             </vsm:VisualStateGroup>
  16:                             <vsm:VisualStateGroup x:Name="StatusStates" >
  17:                                 <vsm:VisualState x:Name="OnState" >
  18:                                     <Storyboard >
  19:                                     </Storyboard>
  20:                                 </vsm:VisualState>
  21:                             </vsm:VisualStateGroup>
  22:                         </vsm:VisualStateManager.VisualStateGroups>
  23:                         <Ellipse x:Name="Core" >
  24:                     </Grid>
  25:                 </ControlTemplate>
  26:             </Setter.Value>
  27:         </Setter>
  28:     </Style>
  29: </ResourceDictionary>   


Notice there is no <Grid.Resources> area, as each <vsm:VisualState> is declared, if there is an associated storyboard it is placed within the VisualState definition.



About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen Pluralsight & LinkedIn Learning courses. He was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP and a Microsoft MVP.
This entry was posted in z Silverlight Archives. Bookmark the permalink.