简单地添加对样式程序集的引用是不够的;你必须做一些事情来让 WPF 合并资源。但是我们可以这样做,你只需要在你的应用程序程序集中添加一行 C#(或几行 XAML)。
最直接的解决方案可能是在您的共享样式程序集中创建一个强类型,并在启动时ResourceDictionary
将其添加到您的应用程序级别。ResourceDictionary
例如,CustomStyles.xaml
在您的共享样式程序集中创建一个,并将所有样式资源拉入该文件(直接或通过MergedDictionaries
)。确保 Build Action 设置为“Page”,并向元素添加x:Class
指令,如下所示:ResourceDictionary
<ResourceDictionary x:Class="YourNamespace.CustomStyles"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Your styles declared or imported here -->
</ResourceDictionary>
对于旨在替换内置或第三方控件样式的样式,您可以将样式声明为隐式,即x:Key
完全不使用该样式,或使用控件的类型作为键,例如x:Key="{x:Type ComboBox}"
.
添加x:Class
指令可能不足以使 Visual Studio 生成CustomStyles()
实际加载 XAML 内容的构造函数,因此您可能需要CustomStyles.xaml.cs
手动添加文件并为其提供调用的构造函数InitializeComponent()
(VS 仍应生成此内容):
namespace YourNamespace
{
partial class CustomStyles
{
public CustomStyles()
{
InitializeComponent();
}
}
}
在您的应用程序中,您需要将此字典合并到您的Application.Resources
字典中。如果您愿意,可以从App.xaml
文件中执行此操作:
<Application x:Class="YourNamespace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cs="clr-namespace:YourNamespace;assembly=YourCustomStylesAssembly">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<cs:CustomStyles />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
...或者您可以在 C# 端执行此操作:
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.Resources.MergedDictionaries.Add(new CustomStyles());
}
}
现在,棘手的部分是让这些样式在 XAML 设计器中工作。想到的一种解决方案是添加一个自定义附加属性,您可以在所有视图上设置该属性,并且仅在您在设计器中运行时应用:
partial class CustomStyles
{
public static readonly DependencyProperty EnableDesignTimeStylesProperty =
DependencyProperty.RegisterAttached(
"EnableDesignTimeStyles",
typeof(bool),
typeof(CustomStyles),
new PropertyMetadata(
default(bool),
OnEnableDesignTimeStylesChanged));
private static CustomStyles DesignTimeResources;
private static void OnEnableDesignTimeStylesChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(d))
return;
var element = d as FrameworkElement;
if (element == null)
return;
if (DesignTimeResources == null)
DesignTimeResources = new CustomStyles();
if ((bool)e.NewValue)
element.Resources.MergedDictionaries.Add(DesignTimeResources);
else
element.Resources.MergedDictionaries.Remove(DesignTimeResources);
}
public static void SetEnableDesignTimeStyles(
DependencyObject element,
bool value)
{
element.SetValue(EnableDesignTimeStylesProperty, value);
}
public static bool GetEnableDesignTimeStyles(DependencyObject element)
{
return (bool)element.GetValue(EnableDesignTimeStylesProperty);
}
}
然后,在您的视图上,只需设置CustomStyles.EnableDesignTimeStyles="True"
强制设计器合并样式资源即可。在运行时,DesignerProperties.GetIsInDesignMode(d)
将评估为false
,并且您最终不会在每个视图中加载样式的新副本;您只需从应用级资源继承它们。