将 WPF ScrollViewer 内容导出为单独的 PNG

Export WPF ScrollViewer content as separate PNGs

在我的 WPF 应用程序中,我有一个 ScrollViewer,它由 DataBindingUserControl 动态填充。想象一下,我的 UserControl 是一个简单的东西,只包含一个标签,标签中显示的值来自一个列表。所以当我 运行 应用程序时,它看起来像下面这样:

如您所见,UserControl 有多个实例,每个实例都具有动态填充的不同值。我的目标是将每个 UserControls 导出为单独的 PNG。我的 EXPORT PNG 按钮点击应该这样做。

所以我环顾四周,发现 this example 可以很好地导出 ScorllViewer.

的全部内容

所以我尝试修改它以实现我的目标,并且我确实让它在一定程度上起作用,但不是我想要的。

这是我的代码:

private void ExportPNG()
{
    var dir = Directory.GetCurrentDirectory();
    var file = "ITEM_{0}.PNG";
    var height = 100.0; // Height of the UserControl
    var width = mainSV.ActualWidth;

    for (int i = 1; i <= ItemList.Count; i++)
    {
        var path = System.IO.Path.Combine(dir, string.Format(file, i));

        Size size = new Size(width, height);
        UIElement element = mainSV.Content as UIElement;
        element.Measure(size);
        element.Arrange(new Rect(new Point(0, 0), size));

        RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
        VisualBrush sourceBrush = new VisualBrush(element);

        DrawingVisual drawingVisual = new DrawingVisual();
        DrawingContext drawingContext = drawingVisual.RenderOpen();

        using (drawingContext)
        {
            drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(width, height)));
        }
        renderTarget.Render(drawingVisual);

        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(renderTarget));
        using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
        {
            encoder.Save(stream);
        }
    }
}

现在导出 5 个 PNG(当我的列表有 5 个项目时),但它们都包含第一个元素的图像:

而且我认为问题可能出在我执行 drawingContext.DrawRectangle() 的地方,因为我的矩形坐标始终相同。所以我尝试将其更改为以下内容,我认为这应该可行,但由于某种原因,它只生成一个 PNG,其中包含第一个 UserControl 和 4 个空 PNG。

using (drawingContext)
{
    drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, (i-1) * height), new Point(width, height + ((i-1) * height))));
}

结果:

我做错了什么?

如果您想运行代码请find it here

请检查以下两种方法。我测试了它,它工作得很好。 1.首先,从你的Items控件中找到children 2. 将它们转换为 PNG。

private void ExportPNG()
            {
                var dir = Directory.GetCurrentDirectory();
                var file = "ITEM_{0}.PNG";
                var height = 100.0;
                var width = 100.0;

                var children = GetChildrenOfType<UCDisplayItem>(itC);


                foreach (var item in children)
                {
                    var path = System.IO.Path.Combine(dir, string.Format(file, DateTime.Now.Ticks));

                    Size size = new Size(width, height);
                    UIElement element = item as UIElement;
                    element.Measure(size);
                    element.Arrange(new Rect(new Point(0, 0), size));

                    RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
                    VisualBrush sourceBrush = new VisualBrush(element);

                    DrawingVisual drawingVisual = new DrawingVisual();
                    DrawingContext drawingContext = drawingVisual.RenderOpen();

                    using (drawingContext)
                    {
                        drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(width, height)));
                        //drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, (i - 1) * height), new Point(width, height + ((i - 1) * height))));
                    }
                    renderTarget.Render(drawingVisual);

                    PngBitmapEncoder encoder = new PngBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(renderTarget));
                    using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
                    {
                        encoder.Save(stream);
                    }

                }
            }

public List<T> GetChildrenOfType<T>( DependencyObject depObj)
   where T : DependencyObject
        {
            var result = new List<T>();
            if (depObj == null) return null;
            var queue = new Queue<DependencyObject>();
            queue.Enqueue(depObj);
            while (queue.Count > 0)
            {
                var currentElement = queue.Dequeue();
                var childrenCount = VisualTreeHelper.GetChildrenCount(currentElement);
                for (var i = 0; i < childrenCount; i++)
                {
                    var child = VisualTreeHelper.GetChild(currentElement, i);
                    if (child is T)
                        result.Add(child as T);
                    queue.Enqueue(child);
                }
            }

            return result;
        }

结果