March 27, 2007
12:47 PM

Sometime last year I ran into an issue where certain templates were not being applied inside a DataTemplate.

Here's a XamlPad ready sample. If you can explain why the style isn't applied to the TextBlock inside the DataTemplate I'm all ears.

What's odd here:

  1. A Style is applied to a Button inside the DataTemplate
  2. The TextBlock style is applied if it's defined inside Application.Resources
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <Grid.Resources>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="Background" Value="Cyan" />
        </Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Cyan" />
        </Style>
        <DataTemplate DataType="{x:Type sys:Int32}">
            <TextBlock>Int32 DataTemplate</TextBlock>
        </DataTemplate>
        <DataTemplate x:Key="template">
            <StackPanel>
                <ContentControl>
                    <ContentControl.Content>
                        <sys:Int32>1</sys:Int32>
                    </ContentControl.Content>
                </ContentControl>
                <TextBlock>inside template</TextBlock>
                <Button>inside template</Button>
            </StackPanel>
        </DataTemplate>
    </Grid.Resources>
    <StackPanel>
        <ContentControl ContentTemplate="{StaticResource template}" />
        <TextBlock>outside template</TextBlock>
        <Button>outside template</Button>
    </StackPanel>
</Grid>

I posted this as a "bug" on Connect in October 2006. A few days later I got a reply:

"Thank you for bringing this to our attention. The situation described is not as intuitive as it should be and is something we will look at fixing in the future. The desired effect can still be achieved by placing x:Key on the Style in question and refering to that Style by key explicitly in the DataTemplate and elsewhere.

Ok, not intuitive, might be fixed, I still don't understand what's happening. The workaround isn't useful to me because the element I'm really trying to style, a Hyperlink, is nested deeply in elements I might not have ownership of.

But, today the bug was closed and the following response given:

"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.

Uh oh, "by design". But this explanation fails to account for why the Button can lookup a style beyond the DataTemplate boundary - unless of course, that's the real bug.

Update: After a lot of digging, I found a part of the (internal) WPF implementation (System.Windows.FrameworkElement.FindImplicitStyleResource) which specifies that Control and subtypes are not subject to the "template encapsulation boundary". Now, if someone could just point me to the relevant documentation.

Templates are viewed as an encapsulation boundary when looking up an implicit style for an element which is not a subtype of Control.

© Douglas Stockwell 2007
Creative Commons License Unless otherwise specified all "source code" examples are available for use under the Creative Commons Attribution-Noncommercial 3.0 License. Please contact me if you would like more flexible licensing terms.
Messenger Presence