Reputation: 21855
I have the following XAML (simplified):
<Window ...
<Window.Resources>
<Style TargetType="{x:Type TextBlock}" >
<Setter Property="FontSize" Value="28" />
<Setter Property="Margin" Value="3" />
<Setter Property="Foreground" Value="Green" />
</Style>
</Window.Resources>
<StackPanel>
<ListBox ItemsSource=...
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Index}" />
<TextBlock Text="-" />
<TextBlock Text="{Binding Hours, StringFormat={}{0:00}}" />
<TextBlock Text=":" />
<TextBlock Text="{Binding Minutes, StringFormat={}{0:00}}" />
<TextBlock Text=":" />
<TextBlock Text="{Binding Seconds, StringFormat={}{0:00}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
...
With this code the Style defined in the Window.Resources is not being applied to the TextBlock inside the DataTemplate but it is on other TextBlocks on the Window.
If I copy the Style and set it in the DataTemplate resources like this:
<DataTemplate.Resources>
<Style TargetType="{x:Type TextBlock}" >
<Setter Property="FontSize" Value="28" />
<Setter Property="Margin" Value="3" />
<Setter Property="Foreground" Value="Green" />
</Style>
</DataTemplate.Resources>
Then it works. Any idea why do I need to duplicate the style?
Thanks in advance.
Upvotes: 4
Views: 500
Reputation: 22749
It's a WPF quirk. When a control doesn't inherit from Control
, but directly from FrameworkElement
, implicit style lookup inside a template skips directly to the application resources. If you put the style in the application resources (App.xaml
) it would work.
Alternatively, you can use a named resource and BasedOn
to reference it:
<DataTemplate.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource MyTextStyle}" />
</DataTemplate.Resources>
Upvotes: 3
Reputation: 18116
Please take a look DataTemplate and Style Confusion:
I posted this as a "bug" on Connect in October 2006.
...
"This behavior is 'By Design' and this is why. Templates are viewed as an encapsulation boundary. Elements produced by these templates fall within this boundary. And lookup for a style with a matching TargetType stops at this boundary. Hence the TextBlock in the repro which is produced through a template does not pick up the Style in question. Whereas the TextBlock defined outside the template does.
One way to work around this problem is to give an explicit name to the Style and reference the style by this name on the TextBlock within the template.
Upvotes: 2
Reputation: 33384
Implicit Styles
will apply in templates only to types that inherit from System.Windows.Controls.Control
and since TextBlock
inherits directly from System.Windows.FrameworkElement
it won't work. You have to either give your style x:Key
and use it explicitly or declare your style in Application.Resources
but then it will apply to all TextBlocks
and by this I mean basically every displayed bit of text, in whole application
Upvotes: 4