我认为唯一的方法是为每个主题创建资源字典,就像您创建自定义控件并希望为每个主题提供不同外观时所做的那样。然后,您将为每个 ComboBox 创建一个 Style,并使用 ResourceKey 派生类(例如 ComponentResourceKey)作为 Style 的 x:Key,在每个主题的资源字典中使用相同的 x:Key 值。然后,当您引用该 Style 时,您将使用 DynamicResource 引用该 ResourceKey。
因此,一个简化的示例是创建一个新的 WpfApplication(例如,我将其命名为 WpfResourceKeys)。在这种情况下,我将主题资源字典放在主程序集中,因此我进入 AssemblyInfo.cs 并将 ThemeInfo 的第一个参数(即 themeDictionaryLocation)设置为 SourceAssembly。
然后创建一个名为“themes”的文件夹,并在其中为要支持的每个主题创建一个资源字典。例如,aero.normalcolor.xaml、aero2.normalcolor.xaml、luna.normalcolor.xaml、classic.xaml 等。
在每个ResourceDictionary中定义一个ComboBox或其他控件的样式,并将其x:Key设置为相同的ResourceKey。最简单的方法是使用
ComponentResourceKey。在我的情况下,我将使用TextBox,因为我只需要设置背景色,而不管每个主题定义的模板如何,都会被尊重。例如:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:WpfResourceKeys"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBox"
x:Key="{ComponentResourceKey
ResourceId=Foo,
TypeInTargetAssembly={x:Type local:MainWindow}}">
<Setter Property="Background" Value="Purple" />
</Style>
</ResourceDictionary>
在我的情况下,我只是将这个放到每个主题的xaml文件中,但是为了测试,Background设置器的值不同。所以在我的aero2.normalcolor.xaml中,setter值为紫色,在classic.xaml中,setter值为橙色。当我在Windows 8上运行我的测试时,如果我切换到高对比度主题之一,TextBox将变为橙色。
然后,在您要引用它的位置,您将使用DynamicResource而不是StaticResource,因为您不会在窗口或app.xaml的资源中定义样式(因为您希望框架考虑操作系统主题来定位它)。
<Window x:Class="WpfResourceKeys.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfResourceKeys"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox Style="{DynamicResource ResourceKey={ComponentResourceKey
ResourceId=Foo,
TypeInTargetAssembly={x:Type local:MainWindow}}}" Text="ABC" />
</Grid>
您只需要确保使用与主题字典中定义的等效资源键相同。对于ComponentResourceKey来说,这意味着ResourceId和TypeInTargetAssembly是等效的。