如果没有WPF从Aero恢复到Classic,如何更改按钮的默认样式?

dev*_*xer 6 wpf xaml themes

我已将PresentationFramework.Aero添加到我的App.xaml合并词典中,如...

<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>
Run Code Online (Sandbox Code Playgroud)

我正在尝试稍微修改按钮的默认外观.我把这个样式放在我的ButtonResourceDictionary中:

<Style TargetType="Button">
    <Setter Property="Padding" Value="3" />
    <Setter Property="FontWeight" Value="Bold" />
</Style>
Run Code Online (Sandbox Code Playgroud)

所有按钮现在都有正确的填充和粗体文本,但它们看起来是"经典",而不是"Aero".如何修复此样式,以便我的按钮看起来都是Aero,但也有这些微小的变化?我宁愿不必Style为每个按钮设置属性.

更新

我应该首先提到这一点,但如果我尝试使用BasedOn,如下所示,我得到一个StackOverflowException:

<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}">
    <Setter Property="Padding" Value="3" />
    <Setter Property="FontWeight" Value="Bold" />
</Style>
Run Code Online (Sandbox Code Playgroud)

这通常会起作用,但不会合并到Aero词典中.如果我对这些词典进行评论,则异常消失.

更新2

如果我添加一个x:Key属性并手动设置样式,它可以正常工作(带有填充和粗体的Aero样式),但正如我所说,我更喜欢该样式全局自动应用于所有按钮.

更新3

我刚刚发现了一种新的皱纹.在我的应用程序中,ButtonResourceDictionary.xaml被放置在类库中(即,在外部项目中).如果我将此文件移动到本地文件夹,一切正常.因此,问题似乎是引用各种外部资源字典引起的不良交互.我正在纠正我的App.xaml代码片段(上面),以反映ButtonResourceDictionary实际上是在外部定义的.

And*_*uus 8

我希望你在此期间找到了解决方案.对于其他人来说,这是一个解决方法,这是另一个.我不确定这是否会对您的具体情况有所帮助(尤其是您引用嵌入式资源字典的事实).

UPDATE

这是我提出的解决方案:

<Style TargetType="TextBox" BasedOn="{Common:StaticApplicationResource {x:Type TextBox}}">
    <Setter Property="Height" Value="21"/>
</Style>
Run Code Online (Sandbox Code Playgroud)

StaticApplicationResource我写的自定义MarkupExtension 在哪里简单地调用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样我就不必在我的App.xaml文件之外引用我的资源字典了,这是我喜欢的方式:).您也可以在其中放置更复杂的逻辑,允许您以任何方式解析BasedOn样式.这是一篇很好的文章,向您展示如何从代码中加载资源字典(以及框架自动解析的那些字典).