Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I alter the default style of a button without WPF reverting from Aero to Classic?

Tags:

wpf

xaml

themes

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">
    <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.

like image 529
devuxer Avatar asked May 25 '10 02:05

devuxer


1 Answers

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.

like image 118
Andre Luus Avatar answered Sep 30 '22 17:09

Andre Luus