在另一个中包含一个 ResourceDictionary

Include one ResourceDictionary in another

我正在为我的 C#/XAML 应用程序设计一些主题,我想在一个 XAML 文件 (ResourceDictionary) 中定义我的主题,在几个文件中有不同的颜色其他 XAML 个文件(ResourceDictionaries)。

所以,我正在尝试:

<Style TargetType="ListBox">
    <Setter Property="Foreground" Value="{StaticResource ResourceKey=ForegroundBrush}" />
    <Setter Property="Background" Value="{StaticResource ResourceKey=BackgroundBrush}" />
</Style>

在 class 库中的通用主题 XAML 文件中,我的主应用程序未引用该文件。然后我有第二个文件:

<Color x:Key="BackgroundColour" A="#FF" R="#10" G="#10" B="#40" />
<Color x:Key="BackgroundColour2" A="#FF" R="#10" G="#10" B="#FF" />
<Color x:Key="BorderColour" A="#FF" R="#00" G="#00" B="#FF" />
<Color x:Key="ForegroundColour" A="#FF" R="#FF" G="#FF" B="#FF" />
<Color x:Key="ForegroundColour2" A="#FF" R="#80" G="#80" B="#FF" />

<LinearGradientBrush x:Key="GradientForegroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="{StaticResource ForegroundColour}" Offset="0"/>
    <GradientStop Color="{StaticResource ForegroundColour2}" Offset="1"/>
</LinearGradientBrush>

我显然可以让这些文件中的几个在相同的基本主题上定义不同的颜色。我尝试过:

<ResourceDictionary Source="basestyle.xaml" x:Key="basestyle" />

然后我会从我的应用程序中引用 bluestyle.xamlredstyle.xaml 等...。如果我将整个主题复制到每个文件,这会很好用,但能够重用基本代码似乎更整洁。

有办法吗?

是的,你可以在同一个项目中创建不同的 Resource.xaml 文件,你只需要在 App.cs 代码中加载这些文件,

if(_theme=="theme1")//you can use switch statement if themes are more
{
   ResourceDictionary myResourceDictionary1 = new ResourceDictionary();
   myResourceDictionary1.Source = new Uri("theme1.xaml", UriKind.Relative);
   Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary1);
}
else
{
   ResourceDictionary myResourceDictionary2 = new ResourceDictionary();
   myResourceDictionary2.Source = new Uri("theme2.xaml", UriKind.Relative);
   Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary2);
}
        

如果您想将画笔或特定样式等资源与您的主题样式和控件模板分开,您可以简单地创建通用 Themes\Generic.xaml 资源字典,其中包含对资源键的引用,就像您在示例中所做的那样例如ForegroundBrush.

然后您可以创建特定样式的资源字典,例如redstyle.xaml 包含具有对应键的所有资源。或者,您可以另外创建另一个 basestyle.xaml 资源字典,其中包含您不想存储在主题资源字典中的所有具体主题变体共享的一些资源。

为了应用样式,将必要的资源词典作为合并词典添加到 App.xaml 文件中。请注意,顺序很重要。首先包含其他资源字典需要的资源字典。 StaticResources 和 DynamicResources 的查找将找到具有匹配键的资源,该键是最后在此处添加的。有关详细信息,请参阅 Lookup behavior for XAML resource references.

<Application x:Class="YourApplication"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Application.Resources>
      <ResourceDictionary>
         <ResourceDictionary.MergedDictionaries>
            
            <!-- Base style that includes all default resources and styles. -->
            <ResourceDictionary Source="basestyle.xaml"/>
            
            <!-- Red style that includes just specific resources and style that changed. -->
            <ResourceDictionary Source="redstyle.xaml"/>
            
            <!-- Your control theme that references the resources and styles. -->
            <ResourceDictionary Source="Themes/Generic.xaml"/>

         </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
   </Application.Resources>
</Application>

如果您打算在运行时切换样式,则需要在代码中替换相应的字典,例如:

  • App.xaml.cs中通过修改Resources词典
  • 通过使用 Application.Current.Resources.

如果你不替换所有词典,包括你的通用控制主题词典,你将不得不使用DynamicResource markup extension instead of StaticResource,因为后者不接在运行时更改引用资源。

The StaticResource Markup Extension processes a key by looking up the value for that key in all available resource dictionaries. Processing happens during load, which is when the loading process needs to assign the property value. The DynamicResource Markup Extension instead processes a key by creating an expression, and that expression remains unevaluated until the app runs, at which time the expression is evaluated and provides a value.