Jeff
Jeff

Reputation: 36573

Styling a ContentControl

I have a custom WPF control. It has a nested ContentControl which is bound to the template's Content property, so it can have any object set as its content.

IF the content is a raw string, I want to apply the following style to the TextBlock (I know that when the Visual Tree is actually rendered a ContentPresenter with a TextBlock is generated if you set a ContentControl's Content property to a string).

<Style x:Key="Label" TargetType="TextBlock">
    <Setter Property="TextWrapping" Value="Wrap" />
    <Setter Property="FontSize" Value="14" />
    <Setter Property="Foreground">
        <Setter.Value>
            <SolidColorBrush>
                <SolidColorBrush.Color>
                    <Color A="255" R="82" G="105" B="146" />
                </SolidColorBrush.Color>
            </SolidColorBrush>
        </Setter.Value>
    </Setter>
</Style>

I would have thought the way to do this was via nested resources (this is part of my custom control):

<ContentControl x:Name="SomeText" Margin="10,10,10,0"
                Content="{TemplateBinding Content}"
                IsTabStop="False" Grid.Column="1">
    <ContentControl.Resources>
        <Style TargetType="TextBlock" BasedOn="{StaticResource Label}" />
    </ContentControl.Resources>
</ContentControl>

So...the above says (to me) if the ContentControl ends up with a nested TextBlock, we should apply the Label style, right?...but no, the Label style is not applied in the example above.

How can I accomplish this?

Thanks.

Upvotes: 3

Views: 1979

Answers (1)

Fredrik Hedblad
Fredrik Hedblad

Reputation: 84656

Update

For an explanation of why the Style for the created TextBlock isn't getting applied, see answer 5 at this link: Textblock style override label style in WPF

This is because ContentPresenter creates a TextBlock for a string content, and since that TextBlock isn't in the visual tree, it will lookup to Appliacton level resource. And if you difine a style for TextBlock at Appliaction level, then it will be applied to these TextBlock within ControlControls.

You could use a DataTemplateSelector

<DataTemplate x:Key="stringTemplate">
    <TextBlock Style="{StaticResource Label}"/>
</DataTemplate>
<local:TypeTemplateSelector x:Key="TypeTemplateSelector"
                            StringTemplate="{StaticResource stringTemplate}" />

<ContentControl ContentTemplateSelector="{StaticResource TypeTemplateSelector}"
                ...>

TypeTemplateSelector example

public class TypeTemplateSelector : DataTemplateSelector
{
    public DataTemplate StringTemplate { get; set; }

    public override System.Windows.DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is string)
        {
            return StringTemplate;
        }
        return base.SelectTemplate(item, container);
    }
}

You'll also have to Bind the Text property for the TextBlock

<Style x:Key="Label" TargetType="TextBlock">
    <Setter Property="Text" Value="{Binding}"/>
    <!-- Additional setters.. -->
</Style>

Upvotes: 5

Related Questions