我相信这样做的唯一方法是为每个主题创建资源字典,就像您创建自定义控件并希望每个主题具有不同的外观一样。然后,您将在每个 ComboBox 中创建一个 Style 并提供一个 ResourceKey 派生类(例如 ComponentResourceKey)作为 Style 的 x:Key,使用每个主题的资源字典中 x:Key 的相同值。然后,当您引用样式时,您将使用该 ResourceKey 的 DynamicResource。
因此,一个简化的示例是创建一个新的 WpfApplication(例如,我将其命名为 WpfResourceKeys)。在这种情况下,我将把主题资源字典放在主程序集中,因此我进入AssemblyInfo.cs并将ThemeInfo的第一个参数(即themeDictionaryLocation)设置为SourceAssembly。
然后创建一个名为“主题”的文件夹,并在其中为您要支持的每个主题创建一个资源字典。例如 aero.normalcolor.xaml、aero2.normalcolor.xaml、luna.normalcolor.xaml、classic.xaml等。
在每个 ResourceDictionary 中,为 ComboBox 或任何您想要的控件定义一个样式,并为其提供相同 ResourceKey 的x:Key。最容易使用的是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 文件中,但背景设置器使用不同的值来测试它。因此,在我的 aero2.normalcolor.xaml 中,setter 值为 Purple,而在 classic.xaml 中,setter 值为 Orange。当我在 Windows 8 中使用默认主题运行测试时,TextBox 为紫色,但如果我切换到高对比度主题之一,则 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 是等价的。