【发布时间】:2011-07-14 12:44:27
【问题描述】:
我通常对资源字典和合并字典有疑问,尤其是在资源查找性能方面。经过一些性能测试后,我发现 ResourceDictionary.get_MergedDictionaries 是点击次数最多的调用(在 ANTS 分析器中检查)。我们有大约 300 个资源字典 xamls,其中很多都使用合并字典来“包含”其他样式。好吧,get_MergedDictionaries 依赖于我们应用程序的一部分,其中没有发生太多事情,大约有 1000 万次点击。所以我的猜测是我们对资源字典做的完全错误。所以我试图重构一切,我想尝试摆脱所有合并的字典。
现在回到实际问题。我试图摆脱合并的字典,但失败了。我的理解是,当您使用 StaticResource 时,查找需要在当前资源之前定义资源。我做了以下简短的例子:
一个主项目和一个自定义控件库。
自定义控件库包含 2 个 xamls。
<!-- Colors.xaml -->
<ResourceDictionary [stripped namespaces] >
<SolidColorBrush x:Key="myColor" Color="Green"/>
</ResourceDictionary>
<!-- Templates.xaml -->
<ResourceDictionary [stripped namespaces]>
<ControlTemplate x:Key="myTemplate" TargetType="Button">
<Rectangle Fill="{StaticResource myColor}"/>
</ControlTemplate>
</ResourceDictionary>
现在在主项目中,MainWindow.xaml 看起来像这样
<Window x:Class="ResourceTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ResourceTestLib;component/Themes/Colors.xaml"/>
<ResourceDictionary Source="/ResourceTestLib;component/Themes/Template.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Template="{StaticResource myTemplate}"/>
</Grid>
</Window>
这是预期的目标。但不幸的是,这会崩溃,因为找不到资源“myColor”。我当然知道如何修复它,在 Templates.xaml 中添加一个合并字典并引用 Colors.xaml 但我一直认为,我从来没有真正检查过,资源是根据逻辑树和元素的资源来查找的。我的理解是;按钮已创建;尝试查找模板..找到;尝试查找颜色,在自己的资源上没有找到,上去使用windows资源。
看来我错了。 所以我希望有人可以为我阐明这一点。我们大量使用 WPF,尽管如此,我们还是用它完成了很多工作,但是由于一开始的一些错误的学习行为,我们的性能非常糟糕,仅仅是因为资源查找。 任何帮助将不胜感激
提前致谢 最好的祝福 妮可
【问题讨论】:
-
在 MyColor 中使用
DynamicResource而不是StaticResource有什么问题?最后我检查了一下,性能差异不足以证明不使用动态资源。 -
嗯,我主要关心的是性能,我读到的每个性能提示都提到不要使用 DynamicResource,即使 MSDN 也这么说。我的示例源代码也只包含我们问题的最小示例。所以我们讨论了大约 3000-4000 次 StaticResource 调用。
-
你为什么有这么多?通常资源只加载到一个应用程序中一次,因此您应该在整个应用程序中只有一个对
Colors.xaml或Templates.xaml的引用。通常我将通用资源(颜色、模板、样式等)加载到Application.Resources中,而不是将特定资源(如 DataTemplates)加载到使用它们的 UserControl 中。 -
附带说明,我发现 Blend 几乎完全是用 DynamicResources 编写的,它生成的代码总是使用 DynamicResource。如果静态资源和动态资源之间存在显着的性能差异,我认为他们不会这样做。
-
@Rachel 就像我在第一篇文章中写的一样。我一开始就学错了或者理解错了。我们有很多自定义控件,每个自定义控件都有自己的 xaml 及其样式。如果它是一个项目控件,我们还有一个用于容器的 xaml。我们还进一步拆分了 xaml,因此设计者有一个 xaml,他只能在其中修改与设计器相关的内容,而控件的主要 xaml 仅引用设计器的内容。我们这样做是为了让设计人员不必处理绑定和其他与代码相关的事情。看起来这种整洁的结构使情况变得更糟。
标签: wpf performance resourcedictionary staticresource mergeddictionaries