【问题标题】:Can you define multiple TargetTypes for one XAML style?您能否为一种 XAML 样式定义多个 TargetType?
【发布时间】:2010-10-22 14:32:44
【问题描述】:

在 HTML/CSS 中,您可以定义一种可应用于多种元素的样式,例如:

.highlight {
    color:red;
}

可以同时应用于 P 和 DIV,例如:

<p class="highlight">this will be highlighted</p>
<div class="highlight">this will also be highlighted</div>

但在 XAML 中,您似乎必须为样式定义 TargetType,否则会出现错误:

<Style x:Key="formRowLabel" TargetType="TextBlock">

有没有办法允许将 XAML 样式应用于多个元素,甚至像在 CSS 中一样保持打开状态?

【问题讨论】:

    标签: wpf xaml styles


    【解决方案1】:

    在编译时检查 WPF 样式中的设置器; CSS 样式是动态应用的。

    您必须指定一个类型,以便 WPF 可以将设置器中的属性解析为该类型的依赖项属性。

    您可以将目标类型设置为包含所需属性的基类,然后将该样式应用于派生类。例如,您可以为 Control 对象创建样式,然后将其应用于多种类型的控件(按钮、文本框、复选框等)

    <Style x:Key="Highlight" TargetType="{x:Type Control}">
        <Setter Property="Foreground" Value="Red"/>
    </Style>
    

    ...

    <Button Style="{StaticResource Highlight}" Content="Test"/>
    <TextBox Style="{StaticResource Highlight}" Text="Test"/>
    <CheckBox Style="{StaticResource Highlight}" Content="Test"/>
    

    【讨论】:

    • 你可以将它应用到任何你想要的地方。此样式必须应用于控件。如果您删除了“x:Key="Highlight"”,则 If 仅适用于所有控件。如果您不想将其应用于 CheckBox,请不要使用 'Style=' 属性。
    • 澄清:从样式定义中删除 'x:Key="Highlight"' 以将样式应用于该类型的所有实例。使用 键,从控件中删除 'Style="{StaticResource Highlight}"' 以从该控件中删除样式。
    • 但是如果我想设置一个TextBox和一个TextBlock的FontStyle属性。我该怎么办,因为 TextBlock 不继承自 Control ?
    • 为什么这是公认的答案?它不起作用 - 样式不适用于派生类型。请参阅有关该问题的问题:stackoverflow.com/questions/1026635/…
    • @Al-Muhandis 如果您指定要使用的样式,它确实有效,就像他在这里所做的那样:Style="{StaticResource Highlight}"
    【解决方案2】:
    <!-- Header text style -->
    <Style x:Key="headerTextStyle">
        <Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
        <Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
        <Setter Property="Label.FontWeight" Value="Bold"></Setter>
        <Setter Property="Label.FontSize" Value="18"></Setter>
        <Setter Property="Label.Foreground" Value="#0066cc"></Setter>
    </Style>
    
    <!-- Label style -->
    <Style x:Key="labelStyle" TargetType="{x:Type Label}">
        <Setter Property="VerticalAlignment" Value="Top" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="Margin" Value="0,0,0,5" />
    </Style>
    

    我认为这两种声明样式的方法都可以回答您的问题。 在第一个中,没有指定 TargetType,但属性名称以“Label”为前缀。在第二个中,为 Label 对象创建样式。

    另一种方法是:

    <UserControl.Resources>
      <Style x:Key="commonStyle" TargetType="Control">
         <Setter Property="FontSize" Value="24"/>
      </Style>
      <Style BasedOn="{StaticResource commonStyle}" TargetType="ListBox"/>
      <Style BasedOn="{StaticResource commonStyle}" TargetType="ComboBox"/>
    </UserControl.Resources>
    

    【讨论】:

    • headerTextStyle 仍然只能应用于 Label 和派生自它的类,因此离开 TargetType 没有任何好处。
    • @Steve:我想这个可能会回答你的疑问。
    • 对于第一个示例,您可以将Label 替换为UIElement 以使其普遍适用于多种类型的控件
    • “另一种方法”部分是一个很好的选择,它可以让您避免弄乱您的控件标记。如果你这样做,你根本不需要在你的控件上有一个样式属性,只要你有每个控件类型的样式。
    【解决方案3】:

    我想将样式应用于 Textblock 和 TextBox,但所选答案对我不起作用,因为 Textblock 不继承自 Control,在我的情况下,我想影响 Visibility 属性,所以我使用了 框架元素

    <Style x:Key="ShowIfRequiredStyle" TargetType="{x:Type FrameworkElement}">
            <Setter Property="Visibility" Value="Collapsed"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding ShowIfRequiredStyle, UpdateSourceTrigger=PropertyChanged}" Value="true">
                    <Setter Property="Visibility" Value="Visible"/>
                </DataTrigger>
            </Style.Triggers>
    </Style>
    
    <TextBlock Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
    <TextBox Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
    

    这适用于 Visibility 属性,因为这两个项目都继承自 Frameworkelement 并且该属性是在那里定义的。当然,这不适用于仅在 Control 中定义的属性,您可以搜索层次结构树并尝试找到一个基类,无论如何我认为这可以帮助某人,因为这是一个热门搜索结果,并且选择的答案有点不完整。

    【讨论】:

    • yes TargetType="{x:Type FrameworkElement}" 为我工作而不是“控制”
    【解决方案4】:

    这个问题有另一个答案。您可以完全将 TargetType 参数从样式中移除,这将允许它应用于各种不同的控件,但前提是您必须在属性名称前加上“Control”。

    <Style x:Key="Highlight">
        <Setter Property="Control.Foreground" Value="Red"/> 
    </Style> 
    

    显然,这只适用于基本控件类的属性。如果你试图设置 ItemsSource 说,它会失败,因为没有 Control.ItemsSource

    【讨论】:

    • 通过这样做,您隐含地指示了一个 TargetType;正如您所说,它仅在应用它的元素是控件时才有效。因此,除了将 TargetType 设置为 Control 之外,这无济于事。
    【解决方案5】:

    我搞定了

    <Style x:Key="HeaderStyleThin"  TargetType="{x:Type Border}">
        <Setter Property="Background" Value="Black" />
    
        <Style.Resources>
            <Style TargetType="{x:Type TextBlock}">
                   <Setter Property="Background=" Value="Red" />
            </Style>
            </Style.Resources>
    
    </Style>
    

    【讨论】:

      猜你喜欢
      • 2015-04-12
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      • 1970-01-01
      相关资源
      最近更新 更多