Even though I've been working with WPF for over 3 years, I'm still learning some of its idiosyncrasies. A discussion came up recently about whether implicit styles are applied to elements in a template. It turns out that the answer is, it depends on whether the element inherits from Control.
Consider the following example. This example creates an implicit style for a Label and another implicit style for a TextBlock. Then it defines a ControlTemplate for a Control, in which is a Label and TextBlock. Finally, the example adds a Control, TextBlock, and Label to the StackPanel. So this XAML displays a TextBlock and Label, which are part of the Control, and another TextBlock and Label, which are not part of the Control.
<Style TargetType="Label"> <Setter Property="Foreground" Value="Red"/> </Style> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Red"/> </Style>
<Style TargetType="Control"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <StackPanel Background="Beige"> <TextBlock>TextBlock Inside Control</TextBlock> <Label>Label Inside Control</Label> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </StackPanel.Resources>
<Control/> <TextBlock Text="TextBlock outside control"/> <Label Content="Label outside control"/>
Here is a rendering of the XAML:
Surprised? So was I. Apparently, people have been mystified by this for a while. It turns out that implicit styles are applied to elements in templates if the element inherits from Control, but not if the element doesn’t inherit from Control. Why? The reason I was given is that Controls are more obvious than elements, and it's likely that an implicit style for a control should be applied everywhere, where it is less likely that a implicit style for an element should be universally applied. There's a legitimate point to this argument. Consider the following:
<StackPanel> <StackPanel.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="16"/> <Setter Property="Foreground" Value="Green"/> </Style>
<TextBlock HorizontalAlignment="Center" Text="Hello!"/> <Button Content="Click me!" Width="200"/> <TextBlock HorizontalAlignment="Center" Text="Please click the button"/> </StackPanel>
A Button displays strings by eventually creating a TextBlock and adding the string to the TextBlock. If the TextBlock in the Button used implicit styles defined by the application, the XAML would render this way:
That probably isn't the behavior you want. On the other hand, suppose you're creating a cool UI and you want all of your RepeatButtons to have a specific look. If you define the appearance of the RepeatButton once, all RepeatButtons will use have that appearance, even if the RepeatButton is inside a ControlTemplate.
So if you ever run into seemingly inconsistent behavior and wonder what's going on, now you know. If you've run into this and understood what the difference is and wondered why in the world it was designed this way, hopefully this has given you a little bit of insight.