Styles Are Forever – But ControlTemplates Are a Developer’s Best Friend
I’ve been working on a project where I have a Button with a default Style that I wanted to change when the Button was clicked. So let’s say you have a Button and a couple of Styles as shown below:
<UserControl x:Class="SilverlightApplication1.Page" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <UserControl.Resources> <Style x:Key="RedStyle" TargetType="Button"> <Setter Property="FontFamily" Value="Verdana"/> <Setter Property="Foreground" Value="Red"/> <Setter Property="FontSize" Value="11"/> </Style> <Style x:Name="BlueStyle" TargetType="Button"> <Setter Property="FontFamily" Value="Courier New"/> <Setter Property="Foreground" Value="Blue"/> <Setter Property="FontSize" Value="11"/> </Style> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <Button x:Name="MyButton" Content="Style Me" Style="{StaticResource RedStyle}"/> </Grid> </UserControl>
I want the default style for this Button to be RedStyle so I have the Style set to:
Style="{StaticResource RedStyle}"
Now, in the code, I want to change the Style when the UserControl is clicked:
void MyButton_Click(object sender, RoutedEventArgs e) { Style blueStyle = this.Resources["BlueStyle"] as Style; if (blueStyle != null) { this.MyButton.Style = blueStyle; } }
But the problem comes along when you actually click the the control and the following exception is thrown:
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
Wait, why can’t I change my style? You might think that the reason is because assigning the Style as a StaticResource makes it permanent. That’s true. However, the whole truth is that once a Style is assigned to an object, it can never have another Style assigned to it. Let’s test this out by not assigning the Style as a StaticResource in the XAML. Instead, let’s assign it in the constructor:
public Page() { InitializeComponent(); this.MyTextBlock.Style = this.Resources["RedStyle"] as Style; this.MouseLeftButtonUp += new MouseButtonEventHandler(Page_MouseLeftButtonUp); }
Now when we click the control what happens?
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
But I really want to change the Style of the Button when I click it. Enter the ControlTemplate. First, let’s change the default style to include a ControlTemplate:
<Style x:Key="BaseStyle" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid x:Name="Content" Background="Black" Width="200" Height="100"> <Grid.Resources> <Style x:Key="RedStyle" TargetType="TextBlock"> <Setter Property="FontFamily" Value="Verdana"/> <Setter Property="Foreground" Value="Red"/> <Setter Property="FontSize" Value="11"/> </Style> </Grid.Resources> <TextBlock Text="{TemplateBinding Content}" Style="{StaticResource RedStyle}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
Here I’m saying that I want my Button to be a Grid that contains a TextBlock. It looks like this:
Now I’m going to add another ControlTemplate that will turn my text blue and change the font:
<ControlTemplate x:Key="BlueTemplate" TargetType="Button"> <Grid x:Name="Content" Background="Yellow" Width="100" Height="50"> <Grid.Resources> <Style x:Key="BlueStyle" TargetType="TextBlock"> <Setter Property="FontFamily" Value="Courier New"/> <Setter Property="Foreground" Value="Blue"/> <Setter Property="FontSize" Value="13"/> </Style> </Grid.Resources> <TextBlock Text="{TemplateBinding Content}" Style="{StaticResource BlueStyle}"/> </Grid> </ControlTemplate>
My MyButton_Click() method now changes to:
void MyButton_Click(object sender, RoutedEventArgs e) { ControlTemplate blueTemplate = this.Resources["BlueTemplate"] as ControlTemplate; if (blueTemplate != null) { this.MyButton.Template = blueTemplate; } }
Now, when I click the Style Me button, it looks like this:
The reason this now works is that while Style is write-once, the Template property isn’t. It can be set any number of times.
Comments
- Anonymous
June 08, 2009
PingBack from http://hairgrowthproducts.info/story.php?id=7136