我正在WinXP上编写一个WPF应用程序,我用这样的vista主题覆盖了默认主题:
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);
}
它的工作原理很好。当我使用按钮等控件时:
<Button />
样式看起来很好,但是如果我使用具有不同风格的Button:
<Button>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Width" Value="80" />
</Style>
</Button.Style>
</Button>
该样式将使用标准的WinXP样式覆盖指定的主题样式,而不是在其上构建。这对我来说是非常有限的。有没有办法避免这个问题?
答案 0 :(得分:10)
为什么会这样?
使用仅当前主题的资源字典生成样式的默认BasedOn =。您为覆盖主题而显示的技术实际上并未更改正在使用的主题词典:它只是将主题资源字典中的资源添加到应用程序的资源字典中。由于当前主题未更改,因此默认的BasedOn也保持不变。
如何解决
选项1:通过拦截对Win32级别的uxtheme.dll!GetCurrentThemeName的调用来本地覆盖主题。这非常复杂,但适用于所有样式而不会更改XAML。
选项2:使用自定义MarkupExtension设置BasedOn。它看起来像这样:
<Style TargetType="Button" BasedOn="{DefaultAeroStyle Button}"> ...
您的自定义MarkupExtension会在首次使用时加载Aero主题词典并将其存储在静态字段中。它的构造函数将采用Type,其ProvideValue将在字典中查找类型以查找样式。
选项3:将BasedOn设置为中间命名样式。它看起来像这样:
<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>
现在在您的低级词典中,您可以说:
<Style TargetType="Button" BasedOn="{StaticResource ThemeButtonStyle}" />
选项4:使用静态属性和x:静态标记扩展
设置BasedOn