WPF RenderTargetBitmap缺少元素

WPF RenderTargetBitmap缺少元素,wpf,rendertargetbitmap,Wpf,Rendertargetbitmap,我有一个树状视图,在数据模板中显示小图标。我正在尝试使用RenderTargetBitmap将Treeview保存为PNG 图像正确地保存在小数据集上。但是,如果数据集变得太大,一些图标将从最终图像中排除。神奇的数字似乎是200件。树是深还是宽似乎无关紧要,在200个项目之后,图标不会被渲染 添加代码 这是我用来创建图像的代码 RenderTargetBitmap targetBitmap = new RenderTargetBitmap( (int)_t

我有一个树状视图,在数据模板中显示小图标。我正在尝试使用RenderTargetBitmap将Treeview保存为PNG

图像正确地保存在小数据集上。但是,如果数据集变得太大,一些图标将从最终图像中排除。神奇的数字似乎是200件。树是深还是宽似乎无关紧要,在200个项目之后,图标不会被渲染

添加代码

这是我用来创建图像的代码

        RenderTargetBitmap targetBitmap = new RenderTargetBitmap(
            (int)_treeView.ActualWidth,
            (int)_treeView.ActualHeight,
            96, 96, PixelFormats.Default);

        targetBitmap.Render(_treeView);
添加了屏幕截图

请注意树右侧缺少的图标。

现在,如果我折叠了几个分支,从而隐藏了一些其他图标,那么这些图标就包括在内了。这几乎就像RenderTargetBitmap。Render没有能力渲染所有图标。或者它可能与虚拟面板有关。

这里有一个更仔细的观察。

我立刻注意到你的巨大形象。宽度12000。我很惊讶你竟然如此接近

如MSDN所述,纹理宽度/高度受DirectX纹理限制的限制

XAML视觉树的最大渲染大小受Microsoft DirectX纹理的最大尺寸限制;有关更多信息,请参阅资源限制(Direct3D)。此限制可能因应用程序运行的硬件而异。超过此限制的非常大的内容可能会进行缩放以适应。如果以这种方式应用缩放限制,则可以使用“PixelWidth”和“PixelHeight”属性查询缩放后的渲染大小。例如,10000 x 10000像素的XAML可视树可能会缩放到4096 x 4096像素,这是应用程序运行的硬件强制的特定限制的一个示例。

我怀疑这些事情:

  • 虚拟化切断了一些东西——我过去遇到过DataGrid的确切问题,问题是虚拟化。不过你的案子看起来不像
  • 纹理过大可能会导致未定义的行为
您可以尝试禁用硬件加速。这件事导致了相当多的核心错误

除此之外,这将是一个棘手的问题,但我非常确信它会很好地工作:

1) 从根对象开始,递归遍历根对象子对象,直到找到小于1000 x 1000的对象。使用RenderTargetBitmap(BMP)拍摄照片,并将其合并到内存中的BMP。为每个孩子做这件事


你应该能够计算所有这些东西

对于记录:有一个解决方法

使用临时DrawingVisual,而不是使用RenderTargetBitmap直接渲染视觉效果。使用VisualBrush将视觉绘制到DrawingVisual中,然后将RenderTargetBitmap与DrawingVisual一起使用

像这样:

    public BitmapSource RenderVisualToBitmap(Visual visual)
    {
        var contentBounds = VisualTreeHelper.GetContentBounds(visual);

        var drawingVisual = new DrawingVisual();
        using (var drawingContext = drawingVisual.RenderOpen())
        {
            var visualBrush = new VisualBrush(visual);
            drawingContext.DrawRectangle(visualBrush, null, contentBounds);
        }

        var renderTargetBitmap = new RenderTargetBitmap((int)contentBounds.Width, (int)contentBounds.Height, 96, 96, PixelFormats.Default);
        renderTargetBitmap.Render(drawingVisual);

        return renderTargetBitmap;
    }
但是请注意,随着VisualBrush变大,生成的图像变得越来越模糊(在使用高DPI渲染时)。要解决此问题,请使用一系列较小的VisualBrush“瓷砖”,如下所述:

你能帮我试试吗;只需将所有图像设置为2x2图像。你还有200件物品的限制吗?@MeirionHughes哇!有趣。在2x2时,未渲染任何图标。我增加了一点尺寸,然后只有几个图标,比如10个。所以当我问这个问题时,模板被设置为100x100,所以我把它改为150x150,所有的图标都被渲染了!那么到底发生了什么?不知道。。。非常奇怪,我想说你在虚拟化和缓存方面有一些问题。您没有对图像进行任何处理,比如将所有图像存储在同一位图中或其他什么?我是从256x256的内存流创建图像。如果将大小更改为512x512,则渲染的图标会减少。如果更改为100x100,将渲染更多图标。这与更改数据模板大小不同且相反。应用程序中是否显示图标?我的意思不是渲染的图像,只是承载树视图的窗口。这可能是解决方案,但我需要几天的时间来测试。然而,这是一个非常好的提示!正如我在评论中提到的,这与虚拟化无关:虽然最初的海报可能使用了虚拟化,但我肯定没有。我也怀疑这与硬件加速有关,因为RenderTargetBitmap不使用硬件加速。这不是来自RenderTargetBitmap MSDN页面,而是来自MSDN上的其他帖子,其中人们抱怨RenderTargetBitmap的速度;如果我以
64位处理器为目标,我可以成功生成
15000x15000
png图像。尝试保存png时,尝试使用
30000x30000
图像会产生内存错误。在32位处理器上尝试
30000x30000
会在创建
RenderTargetBitmap
时产生内存错误。尝试使用
60000x60000
图像会在调用
Render()
时产生错误。某些设置组合在尝试保存时会生成“general GDI+错误”。我的观点是:资源限制的错误不会被默默地吞没-因此我不认为这是一个资源错误。请附上一个为您生成错误的测试用例,我将告诉您发生错误的原因。(exe和sln)