WPF类库中的程序集范围/根级别样式
我有一个支持WPF(基于本文 )的C#(2008 / .NET 3.5)类库程序集。
我创build了几个窗口,现在正在尝试为它们创build一个通用样式集。 但是,由于它是一个类库(而不是WPF应用程序),我没有一个app.xaml(及其包含的应用程序和相应的Application.Resources)来存储这些样式以进行全局访问。
所以: 如果我没有app.xaml(见上文),我怎样才能创build一个顶级的样式定义集合,这些样式定义将被程序集中的所有xaml文件看到 ? 和/或是否可以添加一个工作的app.xaml到类库?
仅供参考,我曾尝试在ResourceDictionary.xaml文件中创buildResourceDictionary,并将其包含在“Window.Resources”块中的每个窗口中。 原来,解决了button等的风格,但不是封闭的窗口。 我可以把Style="{StaticResource MyWindowStyle}"
放在窗口的开始块中,它会在VSdevise窗口中编译和显示,但是在实际的运行过程中,我得到一个parsingexception(MyWindowStyle找不到;我正在猜测Visual Studio看到包含在该行后面的字典,但CRL更顺序地执行,因此尚未加载ResourceDictionary)。
感谢您的想法,但仍然没有去…显然,类库不隐式地支持generic.xaml用法。 我将generic.xaml添加到我的类库项目,并将其构build操作设置为“资源”。 它包含:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="{x:Type Window}" x:Key="MyWindow"> <Setter Property="Background" Value="Black"/> </Style> </ResourceDictionary>
我想要使用主题的窗口xaml如下所示:
<Window x:Class="MyAssembly.ConfigureGenericButtons" x:ClassModifier="internal" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Style="{StaticResource MyWindow}" Title="ConfigureGenericButtons"> ...Buttons, etc... </Window>
虽然VSdevise窗口没有使用MyWindow风格(即黑色背景)显示窗口,但编译良好并启动。 但是,当包含此类库的应用程序调用导致此窗口显示时,我得到一个XamlParseException:
找不到名为“{MyWindow}”的资源。
我也试过忽略了Style参数,看看窗口是否会默认使用这个样式(我试过用generic.xaml中的x:Key来包含和不包含)。 没有错误,但在generic.xaml中定义的任何东西都没有显示出来。
我在这里做错了什么,或者有什么其他想法可以允许在窗口上使用常用的自定义样式(即,不必在每个窗口的xaml中定义样式) – 但是这不是一个应用?
尝试添加
Style={DynamicResource MyStyle}
在这种情况下你不能使用StaticResource。
这听起来像是一个主题工作。
- 将
/themes/generic.xaml
ResourceDictionary添加到您的项目中。 - 将以下内容添加到AssemblyInfo.cs中:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
- ?
- 利润!
您添加到通用的任何资源都将被所有控件使用。 您还可以通过在themes
目录中包含具有正确主题名称的ResourceDictionary文件来制作特定于configuration文件的主题(Luna,Aero等)。
下面是更多信息的链接: 创build并应用自定义主题
如果你没有一个app.xaml,你仍然可以将它加载到appplication级别的资源中,但是你必须编写代码(而不是xaml)来完成它,类似于这个…
void LoadIt() { ResourceDictionary MyResourceDictionary = new ResourceDictionary(); MyResourceDictionary.Source = new Uri("MyResources.xaml", UriKind.Relative); App.Current.Resources.MergedDictionaries.Add( MyResourceDictionary ) }
看看这个网站的例子: http : //ascendedguard.com/2007/08/one-of-nice-features-about-wpf-is-how.html
WPF博士(或以前称为WPF博士的人)在这个问题上有很好的职位 。
以下是他们创buildApplication对象并添加资源的文章摘录:
if (Application.Current == null) { // create the Application object new Application(); // merge in your application resources Application.Current.Resources.MergedDictionaries.Add( Application.LoadComponent( new Uri("MyLibrary;component/Resources/MyResourceDictionary.xaml", UriKind.Relative)) as ResourceDictionary); }
由于我的程序集通过互操作托pipe,我不得不添加设置ShutdownMode如下,完成时关机:
new Application() { ShutdownMode = ShutdownMode.OnExplicitShutdown };
它像一个魅力工作。
如果将其加载到Window.Resource中,字典仅适用于该窗口的子项。 你需要把它提供给窗口和它的孩子。
尝试加载它在你的app.xaml文件。 这应该使其成为应用程序级资源,而不是窗口级资源。
所以花了很多时间后,我终于明白了这一点。 就是这样:
- 在WPF控件库中,添加一个名为
themes
的新文件夹。 - 在
themes
文件夹内,添加一个名为generic.xaml
的资源字典。 -
在
generic.xaml
,使用以下语法添加您的资源:<SolidColorBrush x:Key="{ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}" Color="Blue" />
-
在您的控制中,使用以下语法来访问此资源:
Background="{StaticResource {ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}}"
注意事项:
- 当您创build新的WPF控件库时,步骤1和2通常由Visual Studio自动完成。
- 我不完全理解
ComponentResourceKey
的第一个参数的用途,但它是必需的。 使用将使用此资源的控件的名称。 - Visual Studio的devise者无法find我的案例中的资源。 这可能是caching问题,我不确定。 但在运行时,它运行整齐。
- 您可以在此MSDN文章中阅读有关此语法的更多详细信息。
希望这可以让一些生活更轻松。