XAML: 如何更改特定 ResourceDictionary 的来源
XAML: How can I change the source of a specific ResourceDictionary
<Application x:Class="CDesign.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CDesign"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/Icons.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/IconsNonShared.xaml"/>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary x:Uid="Accents" x:Name="Accents" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary x:Uid="BaseTheme" x:Name="BaseTheme" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
如何根据 ResourceDictionary
的 x:Name
/x:Uid
更改 ResourceDictionary.MergedDictionaries
中特定 ResourceDictionary
的来源?
谢谢。
我认为您无法根据 x:Name
或 x:Uid
做到这一点。 ResourceDictionary
没有为这些标记属性定义映射。例如,UIElement
标记为 UidPropertyAttribute("Uid")
,因此标记为 x:Uid
属性的 UIElement
将具有可用的值 Uid
属性。 x:Name
同样的故事。但是 ResourceDictionary
没有定义这样的映射,所以这些属性在 xaml 被解析和编译后实际上丢失了。
现在,您可以做什么呢?想到的一个选项是使用您自己的附加 属性 为资源字典分配一个标识符。不幸的是,ResourceDictionary
没有继承自 DependencyObject
,因此我们不能在其上使用附加属性。
然而,有一种技巧可以让我们滥用附加的 属性 语法并仍然达到目标。让我们像这样定义假附加 属性:
public static class ResourceDictionaryExtensions {
private static readonly Dictionary<ResourceDictionary, string> _mapping = new Dictionary<ResourceDictionary, string>();
public static void SetName(ResourceDictionary element, string value) {
_mapping[element] = value;
}
public static string GetName(ResourceDictionary element) {
if (!_mapping.ContainsKey(element))
return null;
return _mapping[element];
}
}
请注意,此定义不同于通常附加的 属性。首先,根本没有附加 属性。其次,GetName
和 SetName
这两个方法不接受 DependencyObject
(就像与附加属性关联的方法一样),但是 ResourceDictionary
。但是,因为我们有 GetName
和 SetName
方法 - 我们可以使用附加的 属性 语法,如下所示:
<Application.Resources>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/Icons.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/IconsNonShared.xaml"/>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary local:ResourceDictionaryExtensions.Name="Accents" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary local:ResourceDictionaryExtensions.Name="BaseTheme" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
即使目标对象 (ResourceDictionary
) 不是依赖对象,而且 属性 根本没有附加 属性。
现在很容易修改目标字典的来源:
var dict = Application.Current.Resources.MergedDictionaries.First(c => ResourceDictionaryExtensions.GetName(c) == "Accents");
dict.Source = new Uri("path to the new dictionary");
<Application x:Class="CDesign.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CDesign"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/Icons.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/IconsNonShared.xaml"/>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary x:Uid="Accents" x:Name="Accents" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary x:Uid="BaseTheme" x:Name="BaseTheme" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
如何根据 ResourceDictionary
的 x:Name
/x:Uid
更改 ResourceDictionary.MergedDictionaries
中特定 ResourceDictionary
的来源?
谢谢。
我认为您无法根据 x:Name
或 x:Uid
做到这一点。 ResourceDictionary
没有为这些标记属性定义映射。例如,UIElement
标记为 UidPropertyAttribute("Uid")
,因此标记为 x:Uid
属性的 UIElement
将具有可用的值 Uid
属性。 x:Name
同样的故事。但是 ResourceDictionary
没有定义这样的映射,所以这些属性在 xaml 被解析和编译后实际上丢失了。
现在,您可以做什么呢?想到的一个选项是使用您自己的附加 属性 为资源字典分配一个标识符。不幸的是,ResourceDictionary
没有继承自 DependencyObject
,因此我们不能在其上使用附加属性。
然而,有一种技巧可以让我们滥用附加的 属性 语法并仍然达到目标。让我们像这样定义假附加 属性:
public static class ResourceDictionaryExtensions {
private static readonly Dictionary<ResourceDictionary, string> _mapping = new Dictionary<ResourceDictionary, string>();
public static void SetName(ResourceDictionary element, string value) {
_mapping[element] = value;
}
public static string GetName(ResourceDictionary element) {
if (!_mapping.ContainsKey(element))
return null;
return _mapping[element];
}
}
请注意,此定义不同于通常附加的 属性。首先,根本没有附加 属性。其次,GetName
和 SetName
这两个方法不接受 DependencyObject
(就像与附加属性关联的方法一样),但是 ResourceDictionary
。但是,因为我们有 GetName
和 SetName
方法 - 我们可以使用附加的 属性 语法,如下所示:
<Application.Resources>
<ResourceDictionary x:Name="ThemeDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/Icons.xaml"/>
<ResourceDictionary Source="pack://application:,,,/AppStyles;component/Resources/IconsNonShared.xaml"/>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary local:ResourceDictionaryExtensions.Name="Accents" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary local:ResourceDictionaryExtensions.Name="BaseTheme" Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
即使目标对象 (ResourceDictionary
) 不是依赖对象,而且 属性 根本没有附加 属性。
现在很容易修改目标字典的来源:
var dict = Application.Current.Resources.MergedDictionaries.First(c => ResourceDictionaryExtensions.GetName(c) == "Accents");
dict.Source = new Uri("path to the new dictionary");