内容控件的样式化

3
我有一个自定义的WPF控件。它有一个嵌套的ContentControl,它绑定到模板的Content属性,因此它可以将任何对象设置为其内容。
如果内容是原始字符串,则我想将以下样式应用于TextBlock(当实际渲染可视树时,如果将ContentControl的Content属性设置为字符串,则会生成一个包含TextBlock的ContentPresenter)。
<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>

我认为实现这个的方法是通过嵌套资源(这是我的自定义控件的一部分):

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

所以...对我来说,上面的内容表明如果ContentControl最终带有嵌套的TextBlock,则应该应用Label样式,是吗?但在上面的示例中未应用Label样式。

我该如何达到这个效果呢?

谢谢。


你尝试过使用Snoop或StyleSnooper来查看实际应用了什么吗? - Ed Bayiates
1个回答

5

更新

关于为什么创建的 TextBlock 的样式没有被应用的解释,请参见此链接中的答案5:WPF中的Textblock样式覆盖标签样式

这是因为ContentPresenter为字符串内容创建了一个TextBlock,而由于该TextBlock不在可视树中,它将查找到应用程序级别的资源。如果您在应用程序级别定义了TextBlock的样式,则将对这些控件中的TextBlock应用该样式。

您可以使用DataTemplateSelector

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

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

TypeTemplateSelector示例

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);
    }
}

您还需要绑定 TextBlock 的 Text 属性

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

这是很多工作...我难道不能更简单地完成吗? - Jeff
@JeffN825:我同意,我更新了我的答案,并使用DataTemplateSelector提供了另一种方法。 - Fredrik Hedblad
微软在这方面有很多问题需要解决。因此,即使是TextBlock.Fontsize也无法正常工作。我拒绝相信不将textblock放入可视树中所带来的性能提升值得这样做。 - Gusdor
您还可以在模板中设置文本绑定:<TextBlock Style="{DynamicResource Label}" Text="{Binding}" /> - Christoph Fink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接