合并字典和资源查找



一般来说,我对资源字典和合并字典有一个问题,特别是在资源查找性能方面。经过一些性能测试,我发现ResourceDictionary。get_MergedDictionaries是命中次数最多的调用(在ANTS分析器中检查)。我们有大约300个资源字典示例,其中许多使用合并字典来"包含"其他样式。get_mergeddictionary计数在我们应用程序的一部分,没有发生什么,大约是1000万次点击。所以我的猜测是我们在资源字典上做了一些完全错误的事情。所以我试着重构一切,我想试着摆脱所有合并的字典。

现在进入实际问题。我试图摆脱合并的字典,但失败了。我的理解是,当您使用StaticResource时,查找需要在当前资源之前定义资源。我做了下面这个简短的例子:

一个主项目和一个自定义控件库。

自定义控件库包含2个示例。

<!-- 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"找不到。我当然知道如何修复它,在模板中添加一个合并字典。xaml和参考颜色。但我一直认为,我从来没有真正检查过,资源是根据逻辑树和元素的资源来查找的。我的理解是;按钮被创建;尝试查找模板..发现;尝试查找颜色,在自己的资源中找不到,走上去使用Windows资源。

看来我错了。所以我希望有人能给我一些启示。我们大量使用WPF,尽管我们用它完成了很多工作,但是由于一开始的一些错误的学习行为,我们的性能非常糟糕,仅仅是因为资源查找。如有任何帮助,不胜感激

提前感谢致以最亲切的问候Nico

嗯,我不喜欢回答我自己的问题,但我想很多人可能会遇到这个问题,我想给他们我们目前的解决方案作为一个选择。

就像我之前说的,我们有很多xaml,大约300个用于各种不同类型的东西,比如共享资源(笔刷,颜色),但也有许多xaml包含不同的datatemplate,样式的控件和自定义控件。一开始,这种拥有大量xaml的方法对我们来说是合理的,因为我们对类也是这样做的,并使它们保持小而有组织。不幸的是,WPF不喜欢这样。拥有的ResourceDictionaries越多,通过MergedDictionaries合并的次数越多,性能就越差。我能给您的最好建议是,尽可能少地使用ResourceDictionary xhtml

我们咬紧牙关,将它们中的许多合并到一个巨大的XAML中,事实上,我们现在通过预编译器来实现这一点,同时保持了两个世界的优点。我们可以使用任意多的XAML,只需遵循一些约束,并在一个巨大的XAML中合并它们。我们得到的性能提升是显著的。在我的问题中,我在getmergeddictionaries.com上写了"1100万次点击"。…只是"precompiling"我们的一个程序集,点击率下降到200万,整个应用程序的性能在任何时候都好得多。

所以最后。XAML资源不应该被视为编译的源代码,相反,它应该被理解为一个实际的资源,当声明时,存在,占用空间和性能。

好吧,我们必须以艰难的方式学习。我希望每个读到这篇文章的人都能从我们的错误中吸取教训,从而改进他们的项目。

我倾向于在一个应用程序中只使用一个ResourceDictionary,以避免任何性能问题。

为了使XAML易于管理,我使用了XAML区域Visual Studio插件,并将每个类别的资源包装在一个区域中。

  • 文本样式
  • 等等…

在这种情况下,这个插件是绝对的救星。http://visualstudiogallery.msdn.microsoft.com/3c534623-bb05-417f-afc0-c9e26bf0e177

使用SharedResourceDictionary而不是ResourceDictionary完全解决了我的合并字典性能问题:http://www.wpftutorial.net/MergedDictionaryPerformance.html

对资源查找过程有任何说明吗?为什么没有找到"myColor"?

顺便说一下,我找到了一种让它工作的方法——但是一种奇怪而不稳定的方法。如果应用程序。Xaml有这样的代码,应该找到颜色:
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/ResourceTestLib;component/Themes/Colors.xaml"/>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/ResourceTestLib;component/Themes/Template.xaml"/> 
        </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
另一方面,如果您将此代码包含到另一个XAML中,然后将其包含到Application中。xaml -它不能工作,即使资源结构是相同的(用Snoop验证)。

最新更新