在WPF中,我能否拥有一个样式同时适用于多个TargetType?

32

如标题所述,我的意思是像下面这样的东西:

<Style TargetType="{x:Type TextBlock}" 
       TargetType="{x:Type Label}"  
       TargetType="{x:Type Button}" >

实际上我是为了使用第三方控件而继承他们的类。但是模板并不适用于子类,因为TargetType是在基类上。所以我想设置多个TargetType以使其能够同时适用于两个类。


可能是Can you define multiple TargetTypes for one XAML style?的重复问题。 - StayOnTarget
5个回答

58

不可以,但我通常会为共享基类(如FrameworkElement)创建样式,然后创建以基础样式为BasedOn的个体控件样式。

不行,但我通常会为共享基类(例如FrameworkElement)创建一个样式,接着创建那些基于基础样式的个体控件样式。

<Style TargetType="{x:Type FrameworkElement}">
    <!-- Shared Setters -->
</Style>

<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />

4
不幸的是,FrameworkElement 没有包括许多属性(例如与字体相关的属性),因此它们无法包含在样式设置器中。您可以选择使用 ContentControl,但在这个特定的例子中不起作用,因为 TextBlock 没有继承自 ContentControl - kmote

11

一个更加灵活的变化是使用resourceKey来替代BasedOn,这是对Rachel答案的补充。

所以,不再使用:


<Style TargetType="{x:Type FrameworkElement}">
    <!-- Shared Setters -->
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />


做类似以下的事情:

<Style x:Key="commonStyle" TargetType="{x:Type FrameworkElement}">
    <!-- Shared Setters -->
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource commonStyle}" />


这样做可以拥有更多的选择,因为一些样式可以基于commonStyle,而另一些则可以基于例如commonStyle2,其中commonStyle和commonStyle2都以FrameworkElement作为目标类型。


2

根据Rachel的回答,为了让代码更加简洁,您可以在Markup Extension中删除x:Type并只使用Type:

<Style TargetType="Label">
    <!-- Shared Setters -->
</Style>

与以下代码等效:

<Style TargetType="{x:Type Label}">
    <!-- Shared Setters -->
</Style>

2
答案是否定的。 TargetType是Style的一个属性,只能被设置一次。为了确保类型安全,样式应该针对特定类型,以便知道要设置哪些属性。
然而,有一个解决方法。您可以将所有类型的常用属性定义在一个样式中。然后为每个特定控件创建特定样式,并使用BasedOn属性从基本样式继承。

0

实际上我发现在网格中你只能设置一个项目的样式。但是,在堆栈面板中,您可以设置多个项目的样式。

看看这段代码:

<Grid>        
    <StackPanel>
        <StackPanel.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="12"></Setter>
                <Setter Property="VerticalAlignment" Value="Center"></Setter>
                <Setter Property="HorizontalAlignment" Value="Center"></Setter>
                <Setter Property="Margin" Value="5"></Setter>
            </Style>
            <Style TargetType="TextBox">
                <Setter Property="Width" Value="100"></Setter>
                <Setter Property="Height" Value="25"></Setter>
                <Setter Property="Margin" Value="5"></Setter>
            </Style>
            <Style TargetType="Button">
                <Setter Property="Margin" Value="5"></Setter>
                <Setter Property="Height" Value="30"></Setter>
                <Setter Property="Width" Value="100"></Setter>
            </Style>
        </StackPanel.Resources>
        <StackPanel Orientation="Horizontal">
            <TextBlock>Kanban ID</TextBlock>
            <TextBox></TextBox>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock>Customer Name</TextBlock>
            <TextBox></TextBox>
        </StackPanel>            
        <Button>Save</Button>
    </StackPanel>
</Grid>

如果您将 <script> 标签移除并放到 <head> 之下,同时将 <script> 改为 <script defer>,则您会发现对象并未被设置,只有最后一个对象的属性被更改。

希望这可以帮助您。


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