我猜测您不想将自定义的ThemeDictionaries
应用于所有按钮。借助以下附加属性(Attached Property)
可以实现这一需求:
public class ResourcesServices
{
public static readonly DependencyProperty ResourcesProperty =
DependencyProperty.RegisterAttached(
"Resources",
typeof(ResourceDictionary),
typeof(ResourcesServices),
new PropertyMetadata(default(ResourceDictionary), OnResourcesPropertyChanged));
public static ResourceDictionary GetResources(DependencyObject obj) => (ResourceDictionary)obj.GetValue(ResourcesProperty);
public static void SetResources(DependencyObject obj, ResourceDictionary value) => obj.SetValue(ResourcesProperty, value);
private static void OnResourcesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement source) || !(e.NewValue is ResourceDictionary resourceDictionary))
{
return;
}
ResourceDictionaryCloner.Clone(resourceDictionary, source.Resources);
}
}
public static class ResourceDictionaryCloner
{
public static ResourceDictionary Clone(ResourceDictionary resource, ResourceDictionary destination)
{
if (resource == null)
{
return null;
}
if (resource.Source != null)
{
destination.Source = resource.Source;
return destination;
}
if (resource.ThemeDictionaries != null)
{
foreach (var theme in resource.ThemeDictionaries)
{
if (theme.Value is ResourceDictionary themedResource)
{
var themeDictionary = new ResourceDictionary();
Clone(themedResource, themeDictionary);
destination.ThemeDictionaries[theme.Key] = themeDictionary;
}
else
{
destination.ThemeDictionaries[theme.Key] = theme.Value;
}
}
}
if (resource.MergedDictionaries != null)
{
foreach (var mergedResource in resource.MergedDictionaries)
{
var themeDictionary = new ResourceDictionary();
Clone(mergedResource, themeDictionary);
destination.MergedDictionaries.Add(themeDictionary);
}
}
foreach (var item in resource)
{
destination[item.Key] = item.Value;
}
return destination;
}
}
现在我们可以在样式中设置资源:
<Style
x:Key="CustomButton"
TargetType="Button">
<Setter Property="local:ResourcesServices.Resources">
<Setter.Value>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="ButtonBackground" Color="Red" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonBackground" Color="Blue" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Setter.Value>
</Setter>
</Style>
因此,可以这样使用:
<Button Content="默认按钮" />
<Button Content="自定义按钮" Style="{StaticResource CustomButton}" />
此答案基于一篇优秀的文章:XAML Lightweight styling done right。