views:

47

answers:

1

Why does the following XAML cause a stack overflow exception with some themes?

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="ExpressionLight.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
            <Setter Property="Margin" Value="5"/>
        </Style>
        <Style TargetType="{x:Type Button}"  BasedOn="{StaticResource BaseButtonStyle}"/>
    </ResourceDictionary>
</Application.Resources>

I have tried several themes found on internet and about half of them causes the exception.

Is there another way to apply a named style as default?

Edit:

The problem is that the Theme adds the default style to the resource dictionary (an entry with the name "System.Windows.Control.Button). Since a dictionary can only contain a single entry for each key it is not possible add a new default within the same resource dictionary.

Don't know why it leads to a "stackoverflow" instead of a "duplicate key" exception. It is probably because of the special handling of merged dictionaries which can contain duplicate keys.

The solution is to apply the named style as default in code

void AppStartup(object sender, StartupEventArgs args) {
    this.Resources[typeof(Button)] = this.Resources["BaseButtonStyle"];
    ....
}

Since the BaseButtonStyle is staticly bound to the theme it is of course not possible to change theme at runtime with this solution.

+2  A: 

you are having circular dependency in this code:

<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Margin" Value="5"/>
</Style>

this style says that it is for TargetType Button, thats fine. it also says that it is BasedOn the Style defined for TargetType Button, which is this itself. Better to assign a key to the previous Style and then use that key in BasedOn.

EDIT:

After going through your code again it seems that there is a circular reference between your style and the style defined in ExpressionLight.xaml. A workaround would be to place resources at different levels.

<Window.Resources>
<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ExpressionLight.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
    <Grid.Resources>
    <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
        <Setter Property="Margin" Value="5"/>
    </Style>
    <Style TargetType="{x:Type Button}"  BasedOn="{StaticResource BaseButtonStyle}"/>
    </Grid.Resources>
    ............
    ...........
    ...........
</Grid>
viky
Sorry but I don't understand. What is "previous style" in this context?
adrianm
Still don't get it. Can you show me how to create a named style extending the theme style? Then make the named style default.
adrianm
i have checked your code again and then edited my answer for you, you can check for the 'Edit' part in the answer.
viky
The problem was not a circular reference but your solution is correct and led me in the right direction.
adrianm