1

关于我的应用程序的简要说明:

我正在开发的应用程序就是这样的贺卡设计师。想象一下,其中有一个背景图像,以及无限数量的“层”(特别是图片)留在背景上,可以移动、调整大小、前后移动等等......

也可以对这些图层应用特定的形状,如星形、椭圆形,.. 制作卡片后,可以保存为 jpeg 文件。

问题

一切正常,但我检测到当形状应用于图层时,会产生内存泄漏。

下面是每一层的UserControl的代码:

<UserControl>
.....
    <Grid x:Name="_myGrid"  >
        <Border x:Name="im_the_problem" BorderThickness="0" OpacityMask="{Binding Path=MyMask.Data, Converter={StaticResource MaskConverter}}">
        <!-- My Image... -->
        </Border>
    </Grid>
</UserControl>

其中 MaskConverter 代码如下:

public class MaskConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter,
       System.Globalization.CultureInfo culture)
    {
        String maskData = value as String;
        if (maskData == null) 
            return null;
        if (maskData == "")
            return null;
        VisualBrush vb = new VisualBrush();
        vb.Visual = XamlReader.Parse(maskData) as Visual;
        return vb;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

参数“MyMask.Data”是我从包含不同形状的文本文件动态加载的 XAML路径(即我正在应用的形状)。

所以,原则是,如果我有名为*im_the_problem*的边界,则不会释放内存。如果我评论*im_the_problem*(所以我只会有没有形状的矩形图层/图片),一切都像魅力一样工作,没有内存泄漏。

问题应该出在 OpacityMask + VisualBrush 中。

难道我做错了什么?还是有已知问题?有没有办法以不同的方式做同样的事情(将形状应用于图片..)?

谢谢。

4

3 回答 3

0

您也许可以尝试将 MyMask.Data 绑定到实际的 Path.Data,并将 Path.Fill 设置为从图像创建的 ImageBrush?

于 2011-07-27T17:15:09.180 回答
0

你需要冻结你的 VisualBrush ;)

于 2012-02-21T14:54:18.847 回答
0

我在 aDataGrid的列模板中遇到了这个问题,我将 a <Canvas><Path /></Canvas>(作为静态资源)用于 a VisualBrush(也是静态资源)并将其OpacityMask用作 a Rectangle。每当重新加载 DataGrid 时,Rectangle不会释放VisualBrush对 的引用OpacityMask,我使用内存分析器工具来显示所有VisualBrush对象都在使用大量内存。

我不明白为什么或如何发生这种情况 - 但我很高兴我并不孤单(即使大约 6.5 年后我遇到了同样的问题......)。

我的 XAML 是这样的:

<DataGrid.Resources>

    <Canvas x:Key="icon" ...>
        <Path ... />
    </Canvas>

    <VisualBrush x:Key="iconBrush" Stretch="Uniform" Visual="{StaticResource icon}" />

</DataGrid.Resources>

<DataGrid.Columns>

    <DataGridTemplateColumn>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Rectangle
                    Fill="{Binding Foreground, ElementName=myDataGrid}"
                    Width="14"
                    Height="14"
                    Margin="4"
                    Visibility="{Binding IconVisibility}"
                    OpacityMask="{StaticResource iconBrush}"
                />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>

    ...

</DataGrid.Columns>

我阅读了该设置IsFrozen = true(使用此技术完成:https ://www.codeproject.com/Tips/72221/Freeze-brushes-directly-in-the-XAML-to-improve-you )将有助于解决画笔的内存问题,但是这似乎根本没有效果。诡异的。

我以为我会进行实验,并且我推断如果问题泄漏了,VisualBrush那么我想知道是否将其作为StaticResource对象引用弄乱了,所以我将其更改为“拥有”对象,如下所示:

    <DataGridTemplateColumn>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Rectangle
                    Fill="{Binding Foreground, ElementName=myDataGrid}"
                    Width="14"
                    Height="14"
                    Margin="4"
                    Visibility="{Binding IconVisibility}"
                >
                    <VisualBrush Stretch="Uniform" Visual="{StaticResource iconBrush}" />
                </Rectangle>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>

这解决了问题!而且我仍然不知道为什么 - 我想知道这是否是 WPF 中的错误?

在相关的说明中,我开始意识到使用 aVisualBrush是多余的,因为我只渲染一个简单的Path-VisualBrush很昂贵,因为它渲染了整个 WPF 视图 - 我还从其他文档中了解到,它Path本身对于渲染简单形状并不是必需的,因为本身是一个完整的UIElementFrameworkElement- 这是“较重”的类型。

我更改了代码以将路径存储在静态资源中的PathGeometry值中,该GeometryDrawing静态资源被加载到DrawingBrush

<GeometryDrawing x:Key="iconDrawing" Brush="Black" Geometry="..." /> 

<Rectangle
    Fill="{Binding Foreground, ElementName=myDataGrid}"
    Width="14"
    Height="14"
    Margin="4"
    Visibility="{Binding IconVisibility}"
    OpacityMask="{StaticResource iconBrush}"
>
    <DrawingBrush Stretch="Uniform" Drawing="{StaticResource iconDrawing}" />
</Rectangle>

这样做也降低了内存使用量,并有望降低性能。

在您的项目中,我看到您没有将路径信息用作资源,但同样的技术适用:将您的路径加载到一个PathGeometry(或者更确切地说,StreamGeometry对象,它更快并且用于不可变几何图形)并将其设置为Drawing对于一个DrawingBrush

于 2017-12-18T03:24:15.353 回答