Note – these posts are put together after a short time with Silverlight 4 as a way of providing pointers to some of the new features that Silverlight 4 has to offer. I’m posting these from the PDC as Silverlight 4 is announced for the first time so please bear that in mind when working through these posts.
There are some new additions around Styles when it comes to Silverlight 4. As in WPF, it’s now possible to style all controls of a particular type.
For example, all buttons in one of these grids will be Blue whereas all buttons in the other will be red;
<UserControl x:Class="SilverlightApplication14.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <StackPanel x:Name="layoutRoot"> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button"> <Setter Property="Background" Value="Blue" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 1" /> <Button Grid.Row="1" Content="Button 2" /> </Grid> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button"> <Setter Property="Background" Value="Red" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 3" /> <Button Grid.Row="1" Content="Button 4" /> </Grid> </StackPanel> </UserControl>
Note that the Styles in question do not have x:Keys on them which makes them implicit styles and so they apply to all controls of the specified type within their scope and so you could e.g. style all buttons at the application level without having to specify a Style property on the button.
If I have multiple implicit styles relating to a particular control then they do not magically combine so, for instance, if I have a new style here at the UserControl level which is trying to make all the FontSize values equal to 36;
view plaincopy to clipboardprint <UserControl x:Class="SilverlightApplication14.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <Style TargetType="Button"> <Setter Property="FontSize" Value="36" /> </Style> </UserControl.Resources> <StackPanel x:Name="layoutRoot"> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button"> <Setter Property="Background" Value="Blue" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 1" /> <Button Grid.Row="1" Content="Button 2" /> </Grid> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button"> <Setter Property="Background" Value="Red" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 3" /> <Button Grid.Row="1" Content="Button 4" /> </Grid> </StackPanel> </UserControl>
then that won’t get combined with the more local implicit styles and the font-sizes will stay unaffected. Implicit styles can still use BasedOn though so I could make what I want work by doing;
<UserControl x:Class="SilverlightApplication14.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <Style x:Key="myStyle" TargetType="Button"> <Setter Property="FontSize" Value="36" /> </Style> </UserControl.Resources> <StackPanel x:Name="layoutRoot"> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button" BasedOn="{StaticResource myStyle}"> <Setter Property="Background" Value="Blue" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 1" /> <Button Grid.Row="1" Content="Button 2" /> </Grid> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button" BasedOn="{StaticResource myStyle}"> <Setter Property="Background" Value="Red" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 3" /> <Button Grid.Row="1" Content="Button 4" /> </Grid> </StackPanel> </UserControl>
and then I get the combination that I was looking for;
Similarly, if a control has an explicitly stated style then it does not pick up anything from the implicit style. For example, if I give Button 4 an explicit style;
<UserControl x:Class="SilverlightApplication14.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <Style x:Key="myStyle" TargetType="Button"> <Setter Property="FontSize" Value="36" /> </Style> </UserControl.Resources> <StackPanel x:Name="layoutRoot"> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button" BasedOn="{StaticResource myStyle}"> <Setter Property="Background" Value="Blue" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 1" /> <Button Grid.Row="1" Content="Button 2" /> </Grid> <Grid Background="White"> <Grid.Resources> <Style TargetType="Button" BasedOn="{StaticResource myStyle}"> <Setter Property="Background" Value="Red" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Button Content="Button 3" /> <Button Grid.Row="1" Content="Button 4" Style="{StaticResource myStyle}"/> </Grid> </StackPanel> </UserControl>
then it no longer picks up anything ( specifically the background colour of Red ) from the implicit style;
and goes back to using the standard background colour.
I think this is a great addition to styling – it’s something that WPF has been able to do since the first version and I’ve always missed having it in Silverlight. You can define implicit styles at any level from the application down and so take much easier control over the “default” look and feel for the application without having to clutter every definition with Style={}.