paul
paul

Reputation: 13516

Is it possible in WPF to define multiple 'keyed'-Styles but with differing TargetTypes?

I am trying to get to grips with WPF Styles.

I was wondering if it is possible to define one Style key and then describe how it should be applied to different TargetTypes.

This approach is not working for me. I get an error message to say that "TargetType 'TextBlock'" does not match the Element "Image".'

It seems strange that every style:type combination needs it's own key name. I am doing something wrong? Is it completely the wrong approach?

e.g. in the Window.xaml:

<TabControl TabStripPlacement="Bottom">
    <TabItem Content="{Binding UserContent}">
        <TabItem.Header>
            <StackPanel Orientation="Horizontal">
                <Image Source="users_24.gif"  Style="{StaticResource TabHdr}"/>
                <TextBlock Text="{x:Static r:Messages.Tab_Users}" Style="{StaticResource TabHdr}"/>
            </StackPanel>
        </TabItem.Header>
    </TabItem>
</TabControl>

and in the Resources.xaml

<Style x:Key="TabHdr" TargetType="{x:Type Image}">
    <Setter Property="Width" Value="20"/>
    <Setter Property="Height" Value="20"/>
    <Setter Property="Margin" Value="2, 1, 2, 1"/>
</Style>

<Style TargetType="{x:Type TextBlock}">
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="Margin" Value="5, 1, 1, 1"/>
</Style>

Upvotes: 0

Views: 481

Answers (2)

AndrewS
AndrewS

Reputation: 6094

You can do that if you plan on explicitly setting the Style as you are (i.e. they are keyed styles - implicit styles are always found using the exact type of the class). You just have to set the TargetType to be the lowest base type that defines all the dependency properties you are setting. So in your case you are setting properties that are defined on FrameworkElement so you can just set the TargetType to FrameworkElement.

<Style x:Key="TabHdr" TargetType="FrameworkElement">
  <Setter Property="Width" Value="20"/>
  <Setter Property="Height" Value="20"/>
  <Setter Property="Margin" Value="2, 1, 2, 1"/>
</Style>

Note: If however you wanted to set something like Background (which is defined on Control) then you wouldn't be able to share that style with Image/TextBlock (which don't derive from Control) but you could create a style where the TargetType is Control in that case. You could even set the BasedOn of that style to the style you have for FrameworkElement so you can still share the other settings. E.g.

<Style x:Key="ctrl" TargetType="Control" BasedOn="{StaticResource TabHdr}">
  <Setter Property="Background" Value="Red" />
</Style>

And then use it on multiple controls. E.g.

<TextBox Style="{StaticResource ctrl}" />
<Button Content="Foo" Style="{StaticResource ctrl}" />

Upvotes: 2

Mones
Mones

Reputation: 543

To short answer your question.. you can't!

You are assigning TabHdr style to a TextBlock, but the style is defined as a Image control style. You can't do that. If all of your control have to have a specific style, you can define a style without a key but with a specific TargetType. For example, in the code you provided, the TextBlock is applied to all TextBlocks.

PS: If you have to create a kind of theme for your application you can inherit and extend a base style using the BasedOn attribute.

Upvotes: 0

Related Questions