Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set Style for all elements inside ContentPresenter

I overrided the template of wpf expander. The header has ContentPresenter

<ContentPresenter x:Name="HeaderContent"
                  Grid.Column="1"
                  Margin="0,0,4,0"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Center"
                  RecognizesAccessKey="True"
                  SnapsToDevicePixels="True"
                  >
    <ContentPresenter.Resources>
        <Style BasedOn="{StaticResource Expanderheader-Naming}" 
               TargetType="{x:Type TextBlock}" />
     </ContentPresenter.Resources>
</ContentPresenter>

Where I tried to add my style for all TextBlocks inside. My style works if I set the header as a property:

<Expander Header="HelloWorld">

But it doesn't when I try to set it in the other manner.

<Expander>
    <Expander.Header>
        <Grid x:Name="MyGrid">
            <TextBlock>Hello Man</TextBlock>
        </Grid>  
    </Expander.Header>
</Expander>

How to set this style for any TextBlocks inside the ContentPresenter?

like image 544
user1706449 Avatar asked Nov 21 '13 09:11

user1706449


1 Answers

You ran into typical style inheritance issue in wpf.

A control looks for its style at the point when it is being initalized. The way the controls look for their style is by moving upwards in logical tree and asking the logical parent if there is appropriate style for them stored in parent's resources dictionary.

To explain to you what you doing wrong in your example lets think like this.

In first example the header properly is just storing "HelloWorld" and later when control is being initalized "HelloWorld" will be injected into ContentPresenter. This approach provides "HelloWorld" with ContentPresenter being it logical parent and so the style is applied properly since the style can be found.

In second example you create a Grid and inside that Grid you have a TextBlock.

At point of control initalization the logical parent of your TextBlock is Grid and futhermore Grid's logical parent is Expander itself. When looking for style for TextBlock the WPF will ask TextBlock's logical parent if it has a proper style in its resources for the TextBlock and the answer will be NO. There is no proper style for the TextBlock inside Grid.Resources and there is no proper style for the TextBlock inside Expander.Resources.

The proper style would be inside ContentPresenter just in this case the ContentPresenter is not part of logical tree.

That is how you lose the style in your second example.

In order to fix this I suggest you to stick to first example or to change where the style is being stored to. Usually all styles shall be stored inside Window.Resources.

EDIT 2 Take a look at this example carefully:

<Window.Resources>
    <Style x:Key="textBlockStyle" TargetType="TextBlock">
        <Setter Property="Background" Value="Blue"/>
    </Style>


    <Style TargetType="Button">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <ContentPresenter>
                        <ContentPresenter.Resources>
                            <Style TargetType="TextBlock" BasedOn="{StaticResource textBlockStyle}"/>
                        </ContentPresenter.Resources>
                    </ContentPresenter>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<StackPanel>
    <Button Content="Yay, it worked!" />
    <Button>
        <Grid>
            <TextBox Text="It doesn't work this way!"/>
        </Grid>
    </Button>
    <Button>
        <Grid>
            <Grid.Resources>
                <Style TargetType="TextBlock" BasedOn="{StaticResource textBlockStyle}"></Style>
            </Grid.Resources>
            <TextBlock Text="Yay it works again! Woop Woop"/>
        </Grid>
    </Button>
</StackPanel>
like image 95
dev hedgehog Avatar answered Oct 27 '22 01:10

dev hedgehog