我有一个支持WPF的C#(2008 / .NET 3.5)类库程序集(基于this article)。
我创建了几个窗口,现在正试图创建一个共同的样式为他们设定。但是,因为它是一个类库(而不是WPF应用程序),所以我没有app.xaml(及其包含的Application和相应的Application.Resources)来存储这些样式以进行全局访问。
所以:我如何创建一个顶级的样式定义集,这些样式定义将被程序集中的所有xaml文件看到,假设我没有app.xaml(见上文)?和/或是否可以将
仅供参考,我确实尝试在ResourceDictionary.xaml文件中创建ResourceDictionary,并将其包含在“Window.Resources”块中的每个窗口中。结果是解决了按钮等的样式......但不适用于封闭的Window。我可以将Style="{StaticResource MyWindowStyle}"
放在Window的开始块中,然后编译并在VS Design窗口中显示,但在实际运行时我得到一个解析异常(找不到MyWindowStyle;我猜是Visual Studio看到的该字典包含在相关行之后,但CRL更顺序地执行,因此尚未加载ResourceDictionary)。
感谢您的想法,但仍然没有...显然类库不会隐式支持generic.xaml用法。我将generic.xaml添加到我的类库项目中,并将其Build Action设置为“Resource”。它包含:
<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>
虽然VS Design窗口没有显示使用MyWindow样式的窗口(即黑色背景),但它编译良好并启动。但是,当包含此类库的应用程序进行调用以导致显示此窗口时,我会收到XamlParseException:
找不到名为“{MyWindow}”的资源。
我也尝试省略Style参数,以查看默认情况下窗口是否会使用该样式(我尝试使用包含和不包含的generic.xaml中的x:Key)。没有错误,但generic.xaml中定义的任何内容都没有出现。
我在这里做错了什么,或者关于如何允许在窗口上使用常见自定义样式的任何其他想法(即,不必在每个Window的xaml中定义样式) - 请注意这一点不是申请表吗?
答案 0 :(得分:14)
尝试添加
Style={DynamicResource MyStyle}
在这种情况下,您无法使用StaticResource。
答案 1 :(得分:13)
这听起来像是主题的工作。
/themes/generic.xaml
ResourceDictionary添加到您的项目中。[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
您添加到通用的任何资源都将被所有控件使用。您还可以通过在themes
目录中包含具有正确主题名称的ResourceDictionary文件来制作特定于配置文件的主题(Luna,Aero等)。
这是指向更多信息的链接:Create and apply custom themes
答案 2 :(得分:3)
如果您没有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
答案 3 :(得分:1)
博士。 WPF(或以前称为WPF博士的人)在这个问题上有一个很棒的post。
这里是他们创建Application对象并添加资源的帖子的摘录:
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);
}
由于我的程序集是通过interop托管的,我必须添加设置ShutdownMode,如下所示并在完成时关闭:
new Application() { ShutdownMode = ShutdownMode.OnExplicitShutdown };
它就像一个魅力。
答案 4 :(得分:0)
如果在Window.Resource中加载它,则该字典仅适用于该窗口的子项。您需要为窗口及其子项提供它。
尝试在app.xaml文件中加载它。这应该使它成为应用程序级资源,而不是窗口级资源。
答案 5 :(得分:0)
所以在花了很多时间之后我终于弄明白了。以下是:
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}}"
注意事项:
ComponentResourceKey
的第一个参数的用途,但它是必需的。使用将使用此资源的控件的名称。希望这会让生活更轻松。
答案 6 :(得分:0)
这是在 .NET类库中共享资源“模块范围”的简单解决方案。重要的是,它似乎在 Visual Studio 中牢固地保留了 XAML设计器显示功能和行为。
首先添加一个新的从ResourceDictionary
派生的 C#类,如下所示。该类的实例将替换需要查看共享资源的类库中每个ResourceDictionary
(或其他带有System.Windows.Control
的组件)上的默认ResourceDictionary
:
ComponentResources.cs:
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;
namespace MyNamespace
{
[UsableDuringInitialization(true), Ambient, DefaultMember("Item")]
public class ComponentResources : ResourceDictionary
{
static ResourceDictionary _inst;
public ComponentResources()
{
if (_inst == null)
{
var uri = new Uri("/my-class-lib;component/resources.xaml", UriKind.Relative);
_inst = (ResourceDictionary)Application.LoadComponent(uri);
}
base.MergedDictionaries.Add(_inst);
}
};
}
请确保分别使用名称空间和程序集文件名(而不是“ \”替换上一个代码段中的 MyNamespace
和 my-class-lib
)。 .dll'扩展名)来自您自己的项目:
将新的ResourceDictionary
XAML 文件添加到您的类库项目中。与“应用程序”程序集不同,Visual Studio UI中没有此选项,因此您必须手动进行操作。这将包含您要在整个类库中共享的资源:
$(ProjectDirectory)\ Resources.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/netfx/2009/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace">
<!-- define the resources to be shared across the whole class library here -->
<!-- example for demonstration -->
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="Red" />
</Style>
<ResourceDictionary>
将 Build Action (构建操作)设置为“页面” ,并确保“文件属性”信息如下所示:
最后,转到项目中需要引用共享资源的 XAML 文件,并替换默认的ResouceDictionary
(通常是在Resources
属性上XAML根元素)和一个ComponentResources
实例。这将保存每个组件的私有资源,如您在上面的代码中所见,构造函数将模块范围的共享单例ResourceDictionary
附加为“合并字典”。对应该看到共享资源的每个控件执行此操作,即使那些没有自己私有资源的控件也是如此。当然,您也可以跳过此步骤以根据需要排除某些控件。例如:
<UserControl x:Class="MyNamespace.UserControl1"
xmlns="http://schemas.microsoft.com/netfx/2009/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace">
<UserControl.Resources>
<local:ComponentResources>
<!-- Keep any existing non-shared resources here from before -->
<!-- Can be empty if this control has no private resources -->
</local:ComponentResources>
</UserControl.Resources>
<!-- to demonstrate that the Style in the above example is effective... -->
<Grid>
<Rectangle Width="10" Height="10" />
</Grid>
</UserControl>
如广告所示,它很好用,包括在 XAML设计器 ...
中