为什么我的TextBlock/TextBox没有应用基本样式中的值?

5

我经常为样式化数据输入表单编写以下类似代码,但我的问题是 TextBoxTextBlock 似乎没有实现 BaseElementStyle 中的 Setters。通常我需要分别定义它们。

这是为什么?有办法解决吗?

我猜测这与它们通常用于其他控件模板有关(例如 TextBlock 在大多数控件中使用,而 TextBox 在 DatePickers 和 ComboBoxes 中使用)。

<Style x:Key="BaseElementStyle" TargetType="{x:Type FrameworkElement}">
    <Setter Property="Margin" Value="5" />
    <Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource BaseElementStyle}" />
2个回答

8
我想提出两种可能的解决方法。看起来Key和Type都可以使用,但是像你的问题情况这样,它们不能同时使用:x:Key="BaseElementStyle" TargetType="{x:Type FrameworkElement}"
  1. using x:Key

    <Style x:Key="BaseElementStyle">
        <Setter Property="FrameworkElement.Margin" Value="5" />
        <Setter Property="FrameworkElement.VerticalAlignment" Value="Center" />
    </Style>
    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource BaseElementStyle}" />
    
  2. using x:Type

    <Style TargetType="{x:Type FrameworkElement}">
        <Setter Property="Margin" Value="5" />
        <Setter Property="VerticalAlignment" Value="Center" />
    </Style>
    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    

谢谢!你教了我一些新东西……我不知道你可以像你在#2中展示的那样基于隐式样式来设置样式。非常好知道! - Rachel

7
还要记住,WPF认为ControlTemplate是一个膨胀边界,并且不会在模板内应用默认样式。例外情况:任何继承自Control的内容都将使用默认样式进行膨胀。由于TextBlock继承自FrameworkElement而不是Control,因此如果您在ControlTemplate中使用它,则还必须手动应用其样式。这对通过手动添加的TextBlocks或通过WPF为字符串Content添加的TextBlocks都适用。下面是一个快速示例:
<Window x:Class="ImplicitStyles.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <Style x:Key="BaseElementStyle">
                <Setter Property="FrameworkElement.Tag" Value="Hello World" />
            </Style>
            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseElementStyle}" />
            <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseElementStyle}" />

            <!-- Default style for TextBlock will not be applied, Tag will be null -->
            <ControlTemplate x:Key="MyContentControlTemplateOne" TargetType="{x:Type ContentControl}">
                <Border BorderBrush="Red" BorderThickness="2">
                    <TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" />
                </Border>
            </ControlTemplate>

            <!-- Default style for Button will be applied, Tag will be Hello World -->    
            <ControlTemplate x:Key="MyContentControlTemplateTwo" TargetType="{x:Type ContentControl}">
                <Border BorderBrush="Red" BorderThickness="2">
                    <Button Content="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" />
                </Border>
            </ControlTemplate>

        </StackPanel.Resources>

        <ContentControl Template="{StaticResource MyContentControlTemplateOne}" />
        <ContentControl Template="{StaticResource MyContentControlTemplateTwo}" />
    </StackPanel>

</Window>

欲了解更多信息,请参阅此博客文章:

http://blogs.msdn.com/b/wpfsdk/archive/2009/08/27/implicit-styles-templates-controls-and-frameworkelements.aspx

这篇博客文章详细介绍了隐式样式、模板、控件和框架元素。

1
谢谢,我没有意识到模板是样式继承的边界。我一直在想为什么DataTemplates内部的TextBlocks没有应用相同的样式。 - Rachel

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