tags:

views:

231

answers:

3

I've added PresentationFramework.Aero to my App.xaml merged dictionaries, as in...

<Application
    x:Class="TestApp.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary
                    Source="/PresentationFramework.Aero;component/themes/Aero.NormalColor.xaml" />
                <ResourceDictionary
                     Source="pack://application:,,,/WPFToolkit;component/Themes/Aero.NormalColor.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpf;component/ResourceDictionaries/ButtonResourceDictionary.xaml" />
                    <!-- Note, ButtonResourceDictionary.xaml is defined in an external class library-->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

I'm trying to modify the default look of buttons just slightly. I put this style in my ButtonResourceDictionary:

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

All buttons now have the correct padding and bold text, but they look "Classic", not "Aero". How do I fix this style so my buttons all look Aero but also have these minor changes? I would prefer not to have to set the Style property for every button.

Update

I should have mentioned this in the first place, but if I try to use BasedOn, as shown below, I get a StackOverflowException:

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

This would normally work, but not with the Aero dictionaries merged in. If I comment those dictionaries out, the exception disappears.

Update 2

If I add an x:Key attribute and manually set the style, it works properly (Aero style with padding and bold), but as I said, I'd prefer that the style is automatically applied globally to all buttons.

Update 3

I just discovered a new wrinkle. In my app, ButtonResourceDictionary.xaml is placed in a class library (i.e., in an external project). If I move this file to a local folder, everything works fine. So, the problem seems to be a bad interaction caused by referencing various external resource dictionaries. I'm correcting my App.xaml code snippet (above) to reflect that ButtonResourceDictionary is actually defined externally.

A: 

Use the BasedOn attribute to inherit the properties from the Aero Style. This should solve your problem.

<Style
  BasedOn="{StaticResource {x:Type Button}"
  TargetType="{x:Type Button}"> 
    <Setter Property="Padding" Value="3" /> 
    <Setter Property="FontWeight" Value="Bold" /> 
</Style>
Mike Brown
I actually tried that, but for some reason, it causes a `StackOverflowException`. And, interestingly, if I comment out the the Aero merged dictionaries, the exception doesn't happen. So, for some reason, when you merge in Aero, you can't base a style on it.
DanM
A: 

Based on your updates, you could do this (admittedly it is hideously ugly):

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

<Style TargetType="{x:Type Button}"
       BasedOn="{StaticResource _buttonStyleBase}" />
Abe Heidebrecht
Thanks, Abe, but it still causes a `StackOverflowException`.
DanM
+1  A: 

Hi Dan

I hope you've found a solution in the meantime. For everyone else, here is one workaround, and here is another. I am not sure whether this will help for your specific case though (especially the fact that you reference an embedded resource dictionary).

UPDATE

Here's a solution I came up with:

<Style TargetType="TextBox" BasedOn="{Common:StaticApplicationResource {x:Type TextBox}}">
    <Setter Property="Height" Value="21"/>
</Style>

Where StaticApplicationResource is a custom MarkupExtension I wrote that simply calls TryFindResource:

[MarkupExtensionReturnType(typeof(object))]
public class StaticApplicationResource : MarkupExtension
{
    public StaticApplicationResource(object pResourceKey)
    {
        mResourceKey = pResourceKey;
    }

    private object _ResourceKey;

    [ConstructorArgument("pResourceKey")]
    public object mResourceKey
    {
        get { return _ResourceKey; }
        set { _ResourceKey = value; }
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (mResourceKey == null)
            return null;

        object o = Application.Current.TryFindResource(mResourceKey);

        return o;
    }
}

This way I don't have to reference my resource dictionaries outside of my App.xaml file , which is the way I like it :). You can also put more complicated logic in there too, allowing you to resolve the BasedOn style any way you like. Here is an excellent article showing you how to load resource dictionaries (and those that the framework resolves automatically) from code.

Andre Luus
Thanks, Andre. Good answer. I basically solved the problem using a technique similar to your first workaround. I moved my customizations to the default button style from the App level to the Window level.
DanM