覆盖覆盖的 WPF 主题 [英] Override Overridden WPF Theme

查看:23
本文介绍了覆盖覆盖的 WPF 主题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 WinXP 上编写 WPF 应用程序,并且我用 vista 主题覆盖了默认主题,如下所示:

I am writing a WPF application on WinXP and I have overridden the default theme with the vista theme like this:

protected override void OnStartup(StartupEventArgs e)
{
  base.OnStartup(e);

  var themerd = new ResourceDictionary();
  themerd.Source = new Uri(@"PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\themes/aero.normalcolor.xaml", UriKind.Relative);

  Resources.MergedDictionaries.Add(themerd);
}

而且大多数情况下都可以正常工作.当我使用按钮等控件时:

And it works fine mostly. When I use control such as a button:

<Button />

样式看起来不错,但如果我使用具有不同样式的 Button,如下所示:

The style looks fine, but if I use a Button with a different style like this:

<Button>
  <Button.Style>
    <Style TargetType="Button">
      <Setter Property="Width" Value="80" />
    </Style>
  </Button.Style>
</Button>

该样式将使用标准的 WinXP 样式覆盖指定的主题样式,而不是在其之上构建.这对我来说是非常有限的.有没有办法避免这个问题?

The style will override the specified theme style with the standard WinXP style instead of building on top of it. This is extremely limiting for me. Is there a way to avoid this issue?

推荐答案

为什么会这样

样式的默认 BasedOn= 是使用当前主题的资源字典生成的.您展示的覆盖主题的技术实际上并没有改变正在使用的主题字典:它只是将主题资源字典中的资源添加到应用程序的资源字典中.由于当前主题没有变化,所以默认的BasedOn也没有变化.

The default BasedOn= for a style is generated using only the current theme's resource dictionary. The technique you show for overriding a theme doesn't actually change the theme dictionary in use: It simply adds the resources from the theme's resource dictionary to the application's resource dictionary. Since the current theme is unchanged, the default BasedOn is also unchanged.

如何解决

选项 1:通过在 Win32 级别拦截对 uxtheme.dll!GetCurrentThemeName 的调用来本地覆盖主题.这非常复杂,但适用于您的所有样式,无需更改 XAML.

Option 1: Locally override the theme by intercepting calls to uxtheme.dll!GetCurrentThemeName at the Win32 level. This is quite complex but works for all your styles with no changes to your XAML.

选项 2:使用自定义 MarkupExtension 设置 BasedOn.它看起来像这样:

Option 2: Set BasedOn using a custom MarkupExtension. It would look like this:

<Style TargetType="Button" BasedOn="{DefaultAeroStyle Button}"> ...

您的自定义 MarkupExtension 将在首次使用时加载 Aero 主题词典并将其存储在静态字段中.它的构造函数将接受一个 Type,它的 ProvideValue 将在字典中查找该类型以找到样式.

Your custom MarkupExtension would load the Aero theme dictionary on first use and store it in a static field. Its constructor would take a Type, and its ProvideValue would look up the type in the dictionary to find the style.

选项 3:将 BasedOn 设置为中间命名样式.它看起来像这样:

Option 3: Set BasedOn to an intermediate named style. It would look like this:

<Application ...>
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="... theme path ..." />
      </ResourceDictionary.MergedDictionaries>

      <Style x:Key="ThemeButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" />
      <Style x:Key="ThemeListBoxStyle" TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}" />
      ...
    </ResourceDictionary>
  </Application.Resources>
</Application>

现在在你的低级词典中你可以说:

Now in your lower-level dictionary you can say:

<Style TargetType="Button" BasedOn="{StaticResource ThemeButtonStyle}" />

选项 4:使用静态属性和 x:Static 标记扩展设置 BasedOn

Option 4: Set BasedOn using a static property and the x:Static markup extension

这篇关于覆盖覆盖的 WPF 主题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆