相关疑难解决方法(0)

MergedDictionaries和资源查找

我一般都遇到资源字典和合并的问题,特别是涉及资源查找性能时.经过一些性能测试后,我发现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>
Run Code Online (Sandbox Code Playgroud)

现在在主项目中,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>
Run Code Online (Sandbox Code Playgroud)

这是理想的目标.但不幸的是,这会崩溃,因为无法找到资源"myColor".我当然知道如何修复它,在Templates.xaml中添加一个mergeddictionary并引用Colors.xaml,但我一直认为,我从未真正检查过,根据逻辑树和元素的资源查找资源.我的理解是; 按钮已创建; 尝试查找模板..发现; 尝试查找颜色,找不到自己的资源,走上去使用Windows资源.

看来我错了.所以我希望有人可以为我阐明这一点.我们大量使用WPF,尽管如此我们已经完成了很多工作,但由于一开始就有一些错误的学习行为,我们的表现非常糟糕,因为资源查找.任何帮助将不胜感激

在此先感谢最好的问候尼科

wpf performance resourcedictionary mergeddictionaries staticresource

21
推荐指数
1
解决办法
1万
查看次数

使用SharedResourceDictionary时内存泄漏

如果你在一些更大的wpf应用程序上工作,你可能会熟悉.因为ResourceDictionaries总是被实例化,所以每次在XAML中找到它们时,我们最终可能会在内存中多次使用一个资源字典.所以上面提到的解决方案似乎是一个非常好的选择.事实上,对于我们目前的项目,这个技巧做了很多......内存消耗从800mb减少到44mb,这是一个非常巨大的影响.不幸的是,这个解决方案是有代价的,我想在这里展示,并希望找到一种方法来避免它,同时仍然使用SharedResourceDictionary.

我做了一个小例子,用共享资源字典可视化问题.

只需创建一个简单的WPF应用程序.添加一个资源Xaml

Shared.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <SolidColorBrush x:Key="myBrush" Color="Yellow"/>

</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)

现在添加一个UserControl.代码隐藏只是默认值,所以我只显示xaml

MyUserControl.xaml

<UserControl x:Class="Leak.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:SharedResourceDictionary="clr-namespace:Articy.SharedResourceDictionary" Height="128" Width="128">

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Leak;component/Shared.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <Grid>
        <Rectangle Fill="{StaticResource myBrush}"/>     
    </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

后面的Window代码看起来像这样

Window1.xaml.cs

// [ ... ]
    public Window1()
    {
        InitializeComponent();
        myTabs.ItemsSource = mItems;
    }

    private ObservableCollection<string> mItems = new ObservableCollection<string>();

    private void OnAdd(object aSender, RoutedEventArgs aE)
    {
        mItems.Add("Test");
    }
    private void OnRemove(object aSender, RoutedEventArgs aE)
    {
        mItems.RemoveAt(mItems.Count - 1);
    }
Run Code Online (Sandbox Code Playgroud)

窗口xaml就像这样

Window1.xaml …

wpf memory-leaks resourcedictionary

12
推荐指数
2
解决办法
9974
查看次数