views:

1120

answers:

2

I am trying to inherit application-level styles for a certain Window in my WPF application, but I'm having trouble getting it to inherit rather than simply override the existing styles.

In App.xaml (under the App.Resources element) I define a style as such:

<Style TargetType="Button">
    <Setter Property="Padding" Value="6"/>
    <Setter Property="FontWeight" Value="Bold"/>
</Style>

And in the XAML fora a certain Window, I define the following under Window.Resources:

<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Padding" Value="6"/>
    <Setter Property="FontWeight" Value="Bold"/>
</Style>

The problem here is that the former (app) style is ignored as if the latter (window) style has overridden it. The BasedOn attribute is set, which is intended to indicate that existing styles should be inherited, as far as I know. Removing the attribute doesn't help either. The only potential cause of which I can think is that {StaticResource {x:Type Button}} only refers to the default WPF style and not the one I have define in App.xaml.

I am aware that this styling behaviour would be possible to accomplish using the x:Key attribute, but I was hoping for a more elegant way that allows me to apply styles with inheritance to all controls within a scope (i.e. application/window).

Update

Thanks for both of your replies. You are indeed right that things work as expected in a sample application. The difference is that I inadvertently failed to mention that the style in App.xaml is contained within a ResourceDictionary, as such:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>

            <ResourceDictionary Source="SettingsDictionary.xaml"/>

            <ResourceDictionary>

                <Style x:Key="DefaultButton" TargetType="Button">
                    <Setter Property="Padding" Value="4"/>
                    <Setter Property="HorizontalAlignment" Value="Center"/>
                    <Setter Property="VerticalAlignment" Value="Center"/>
                </Style>

            </ResourceDictionary>

        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Any suggestion on how to remedy matters in this case?

+1  A: 

I'd second Jeff Wains comment in being surprised that your approach is not working as desired. In fact I'm unable to reproduce your issue via the following steps:

  • Created a new project via VS 2008 C# WPF application wizard.
    • resulting in App.xaml and Window1.xaml just like your example
  • Added a standard button from the toolbox to Window1.
  • Pasted your snippets as is, but modified one property each to observe the desired effect in the first place (having identical properties/values each is not what you intended to demonstrate I guess).

Well, this is just working fine, i.e. the button in Window1 inherits properties from both styles and modifying properties in either one does properly affect the button. Consequently their must be something weird going on behind the scenes in your project/environment? Have you tried a simple repro case like this already?

Steffen Opel
Thanks for the response, though it seems like kek444 tracked down the issue from my update question.
Noldorin
+1  A: 

EDIT

After some research, I've found that the x:Key is being automatically generated if TargetType is set. So, the style in App.xaml is correct. However, the wpf designer is lacking some resource handling skills, and is not displayng both styles. If you build and run the project, both styles will be applied.

If your machine and VS2008 behave like the one upon which I tested your code.

Hope this helps.

EDIT 2

The resources and merged dictionaries in App.xaml have always been quirky. I've solved the problem by moving the first style declaration out of the merged dictionary, like this:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>

            <!--<ResourceDictionary Source="SettingsDictionary.xaml"/>-->

        </ResourceDictionary.MergedDictionaries>

        <Style TargetType="Button">
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="Padding" Value="4"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
        </Style>

    </ResourceDictionary>
</Application.Resources>

Note also that giving the style an explicitly set key other than the {x:Type Button} will make it a non-default style and make it not apply automatically.

It is generally recommended to specify merged dictionaries only for resources from another file, and coded resources in the default space as above.

kek444
Edited the answer after update.
kek444
@kek44: Ahh! That does indeed fix things. (I can't believe I didn't try placing the style elements in that place though; I must have tried several others.) It can see now it makes more sense structurally to define them in this way anyway.Anyway, thanks very much. The bounty is yours. :)
Noldorin
Just to finalise things: if I needed to define certain styles in a separate ResourceDictionary XAML file (to share between assemblies, for example), would there be any way to make inheritance work properly still, as I want here?
Noldorin
Try, as an experiment, putting your first Button style in a separate resource dictionary and referencing it in the app.xaml merged dictionary. I haven't checked, but I'm betting it will work fine. The main point is to have the merged dictionary actually merge an outside file, otherwise it works okay.
kek444