开发者

Override Overridden WPF Theme

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 />

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>

The style will override the specified theme style with the standard WinXP style instead of building on top of i开发者_StackOverflow中文版t. This is extremely limiting for me. Is there a way to avoid this issue?


Why this is happening

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.

How to solve it

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.

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

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

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.

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}" />

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜