ContentControl + RenderTargetBitmap + 空白图像

8
我正在尝试创建一些图表图像,而不必在屏幕上显示这些图表。我已经尝试了很多不同的方法,但似乎没有什么起作用。如果我先在窗口中显示图表,那么代码就能完美运行,但是如果我不在窗口中显示它,那么位图就只有一个黑色边框的白色背景(不知道为什么)。
我尝试在渲染之前将图表添加到边框中,并给边框添加绿色边框刷。在位图中,我看到了绿色的边框刷,然后是黑色边框和白色背景,但没有图表。图表不包含在黑色边框中,所以我不知道那是从哪里来的。
我尝试将图表添加到窗口中,而不调用window.Show(),结果仍然是黑色边框和白色背景。但是如果我调用window.Show(),位图中就会包含图表。
我尝试使用drawingVisual,如此处所述,但结果相同。
以下是代码(不包括将元素添加到边框或窗口中):
private static BitmapSource CreateElementScreenshot(FrameworkElement element, int dpi)
{
    if (!element.IsMeasureValid)
    {
        Size size = new Size(element.Width, element.Height);
        element.Measure(size);
        element.Arrange(new Rect(size));
    }

    element.UpdateLayout();

    var scale = dpi/96.0;

    var renderTargetBitmap = new RenderTargetBitmap
        (
            (int)(scale * element.RenderSize.Width),(int)(scale * element.RenderSize.Height),dpi,dpi,PixelFormats.Default
        );

    // this is waiting for dispatcher to perform measure, arrange and render passes
    element.Dispatcher.Invoke(((Action)(() => renderTargetBitmap.Render(element))), DispatcherPriority.Render);

    return renderTargetBitmap;
}

注意:图表是ContentControl。
有没有办法让图表在不先显示窗口的情况下呈现?
3个回答

9
调用 element.ApplyTemplate() 就可以解决问题了。

1
对我没有用。你把ApplyTemplate插入代码的哪里了? - Ignacio Soler Garcia
抱歉,我已经两年没有回答这个问题了,而且我也无法再访问那段代码了。你可以尝试在 UpdateLayout 之前添加它。 - Kelly
感谢您发布答案。你帮我省了很多麻烦! :) - ihake

2

如果有人在渲染RenderTargetBitmap时遇到类似的问题(获取白色/空白图像),而这些问题出现在StackPanel中的项目上,您可以将它们临时移动到Grid中,然后进行渲染并放回StackPanel中。

Grid grid = new System.Windows.Controls.Grid() { Background = Brushes.White, Width = iWidth, Height = iHeight };
Panel panel = plot.Parent as Panel;

if (panel != null)
{
    panel.Children.Remove(plot);
    grid.Children.Add(plot);

    grid.Measure(new Size(iWidth, iHeight));
    grid.Arrange(new Rect(new Size(iWidth, iHeight)));
}
plot.Measure(new Size(iWidth, iHeight));
plot.Arrange(new Rect(new Size(iWidth, iHeight)));

plot.ApplyTemplate();
plot.UpdateLayout();

grid.ApplyTemplate();
grid.UpdateLayout();

RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(
    iWidth,
    iHeight,
    96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(grid);

PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));

MemoryStream memoryStream = new MemoryStream();
encoder.Save(memoryStream);
bitmap = new System.Drawing.Bitmap(memoryStream);

if (panel != null)
{
    grid.Children.Remove(plot);
    panel.Children.Add(plot);
}

plot.Measure(new Size(iWidthBefore, iHeightBefore));
plot.Arrange(new Rect(new Size(iWidthBefore, iHeightBefore)));
plot.UpdateLayout();

谢谢提醒。我找到了一篇关于这个问题的博客文章,并在另一个SO主题中进行了记录:https://dev59.com/F3E85IYBdhLWcg3w9orw#28626055 - Björn

2

对我而言,调用 element.Arrange() 是缺失的关键步骤。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接