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

标签 wpf silverlight wpf-controls

我覆盖了 wpf 扩展器的模板。
header 有 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 中的任何 TextBlocks 设置此样式?

最佳答案

您在 wpf 中遇到了典型的样式继承问题。

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

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

在第一个示例中, header 仅存储“HelloWorld”,稍后在初始化控件时,“HelloWorld”将被注入(inject) ContentPresenter。这种方法为“HelloWorld”提供了 ContentPresenter 作为它的逻辑父级,因此可以正确应用样式,因为可以找到样式。

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

在控制点初始化时,TextBlock 的逻辑父级是 Grid,而且 Grid 的逻辑父级是 Expander 本身。在寻找 TextBlock 的样式时,WPF 将询问 TextBlock 的逻辑父级是否在其资源中为 TextBlock 提供了正确的样式,答案是否定的。 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>

关于wpf - 为 ContentPresenter 中的所有元素设置样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20116418/

相关文章:

c# - 将表达式与 .NET 微框架结合使用

WPF:屏幕验证

silverlight - 当ViewModel属性更改时,如何启动动画?

wpf - Visibility.Collapsed 和 Visibility.Hidden 之间的区别

c# - 应用程序资源的数据绑定(bind)窗口标题

wpf - Snoop 看不到我的应用程序的子窗口

silverlight - 以编程方式确定文本框的最大适合度 (WP7)

c# - 将 WCF Ria 服务应用程序部署到 IIS6 时遇到问题 - EndpointNotFoundException 服务 Web-AuthenticationService.svc 不存在

c# - 将按钮内容设置为大写

wpf - 如何防止使用控件模板创建的 WPF 自定义控件围绕自身绘制焦点?