2

I have a file MyButtonStyles.xaml which designs the WPF button. This file uses a style to set some colors and fonts:

<ResourceDictionary xmlns......>
    <Style BasedOn="{StaticResource {x:Type Button}} TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="Blue" />
        <Setter Property="FontSize" Value="22" />
    </Style>
</ResourceDictionary>

This button is used in two xaml files. One shows the button as designed in the above style. This happens automatically because the above style has the according TargetType and it does not have an x:Key attribute.

In the other xaml file I use this button as well but the style from above should be extended by another setter property. Doing this by merging the dictionaries and basing on the original style it works:

<ResourceDictionary>
    <ResourceDictionary.MergedDictionary>
        <ResourceDictionary Source="MyButtonStyles.xaml" />
    <ResourceDictionary.MergedDictionary>

    <Style BasedOn="ButtonStylesOrig" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Green" />
    </Style>
</ResourceDictionary>

But for this I have to add an x:Key attribute (ButtonStylesOrig) to the base style. This means that in the first xaml which uses the button the base style will not be applied any more.

Is there a possibility to extend a style without losing the global scope of it (e.g. without using x:Key)?

telandor
  • 869
  • 9
  • 28
  • Then your first style needs a key. You can have only _one_ default style. – Iqon Sep 14 '17 at 11:50
  • You mean: When I add a key to the first style, my second style becomes the new default? – telandor Sep 14 '17 at 12:43
  • 1
    Yes, default is always the style without key. – Iqon Sep 14 '17 at 12:50
  • Your assumptions are wrong, It is impossible to have a Style that does not have a Key. If you dont define it, it still has a key set by default to Key="{x:Type Button}". Change your BasedOn attribute for BasedOn="{x:Type Button}" if you want to use default key on the first style. See the remarks: https://msdn.microsoft.com/en-us/library/system.windows.style.targettype.aspx – Jf Beaulac Sep 14 '17 at 13:04

2 Answers2

6

This works:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="MyButtonStyles.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Grid.Resources>
            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
                <Setter Property="Background" Value="Green" />
            </Style>
        </Grid.Resources>

        <Button Content="Button" />
    </Grid>
</Window>

The key is not to override the resource in the same resource dictionary that you merge your base style into:

WPF Using multiple Resource Dictionaries from multiple projects

mm8
  • 163,881
  • 10
  • 57
  • 88
1

You can't combine multiple default styles of the same type a single resource scope. However, it is possible to build default styles in nested resource scopes.

Suppose you merge MyButtonStyles.xaml into the App.xaml resources. Then you can place your second style with the additional setter into Window.Resources or other deeper nested resources and it will combine the correct implicit styles.

A more localized example:

<Grid>
    <Grid.Resources>
        <ResourceDictionary Source="MyButtonStyles.xaml"/>
    </Grid.Resources>
    <Grid>
        <Grid.Resources>
            <Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Green" />
            </Style>
        </Grid.Resources>
        <Button VerticalAlignment="Top" Margin="20">Both styles</Button>
    </Grid>
    <Button VerticalAlignment="Center" Margin="20">ExampleDictionary style</Button>
</Grid>
grek40
  • 13,113
  • 1
  • 24
  • 50
  • This is interesting. Extending a default style for a specific scope works if it all happens within one file. But if I define a default style for a whole application and I want to extend it in one specific file this is not possible? – telandor Sep 14 '17 at 13:12
  • It depends... files are not a good description of XAML resource scopes... if you merge that one specific file into the same scope as your whole application style, then it won't work. If you merge one specific file into the resources of some nested framework element then it will work. – grek40 Sep 14 '17 at 13:27