为ContentPresenter中的所有元素设置样式

时间:2013-11-21 09:01:07

标签: wpf silverlight wpf-controls

我覆盖了wpf扩展器的模板。 标题包含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>

我试图在里面为所有TextBlocks添加我的样式。 如果我将标题设置为属性,我的风格是有效的:

<Expander Header="HelloWorld">

但是,当我尝试以其他方式设置它时,它不会。

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

如何为ContentPresenter中的任何TextBlock设置此样式?

1 个答案:

答案 0 :(得分:11)

你在wpf。

中遇到了典型的样式继承问题

控件在初始化时查找其样式。控件查找其样式的方式是在逻辑树中向上移动,并询问逻辑父级是否存在父级资源字典中存储的适当样式。

为了向你解释你在你的例子中做错了什么,让我们这样想。

在第一个例子中,标题正好只是存储“HelloWorld”,稍后当控件被初始化时,“HelloWorld”将注入ContentPresenter。这种方法提供了“HelloWorld”,其中ContentPresenter是逻辑父类,因此风格可以正确应用,因为可以找到样式。

在第二个示例中,您创建了一个网格,在该网格内部,您有一个TextBlock。

在控制初始化时,TextBlock的逻辑父级是Grid,而Grid的逻辑父级是Expander本身。在查找TextBlock的样式时,WPF将询问TextBlock的逻辑父级,如果它在TextBlock的资源中具有正确的样式,则答案为NO。 Grid.Resources中的TextBlock没有合适的样式,并且Expander.Resources中没有适当的TextBlock样式。

正确的样式将在ContentPresenter内部,在这种情况下,ContentPresenter不是逻辑树的一部分。

这就是你在第二个例子中失去风格的方式。

为了解决这个问题,我建议您坚持使用第一个示例或更改样式的存储位置。通常所有样式都应存储在Window.Resources中。

编辑2 仔细看看这个例子:

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