Ignacio Soler Garcia
Ignacio Soler Garcia

Reputation: 21855

Why a Listbox DataTemplate does not use the Windows.Resources styles?

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

Answers (3)

Eli Arbel
Eli Arbel

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

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

dkozl
dkozl

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

Related Questions