King Chan
King Chan

Reputation: 4302

Can I have one Style with multiple TargetType in WPF?

As titled, and I mean something like below:

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

This is actually for the sake of using a 3rd party control, I have inherited their class. But the template doesn't apply to the SubClass because the TargetType is on the base class. So I would like to set multiple TargetTypes to make it able to apply for both.

Upvotes: 33

Views: 21095

Answers (5)

lowry0031
lowry0031

Reputation: 190

Based on Rachel's answer, for cleaner code, you can remove the x:Type within the Markup Extension and just use the Type:

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

Is the same as:

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

Upvotes: 2

alterfox
alterfox

Reputation: 1695

A more flexible variation of Rachel's answer is to use resourceKey for BasedOn.

So, instead of:

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


Do something like:

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


This gives more options as some styles can be based on commonStyle, and some on e.g. commonStyle2, where both commonStyle and commonStyle2 have FrameworkElement as target type.

Upvotes: 11

Pat
Pat

Reputation: 668

Actually I found out that in a grid you can only set the style of one item. However, in a stackpanel you can set the style of multiple items.

See this code:

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

If you were to remove the place it below the and change to you will see that the objects aren't set, only the last object's properties is changed.

Hope this helps.

Upvotes: 0

Sofian Hnaide
Sofian Hnaide

Reputation: 2364

The answer is no.

TargetType is a property of Style and can only be set once. To insure type safty, the style should target a specific type in order to know what properties to set.

However, there is a work around. You can take the common properties of all the types you have and define them in one style. Then make specific styles for each of the specific controls and use the BasedOn property to inherit from the basic style.

Upvotes: 2

Rachel
Rachel

Reputation: 132568

No you cannot, however I often create a style for a shared base class such as FrameworkElement, and then create my individual control styles that are BasedOn the base style

<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}}" />

Upvotes: 59

Related Questions