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

时间:2018-01-22 23:33:16

标签: c# wpf user-controls png scrollviewer

在我的WPF应用程序中,我有一个ScrollViewer,它由DataBinding动态填充并使用UserControl。想象一下,我的UserControl很简单,只包含一个标签,标签中显示的值来自一个列表。因此,当我运行应用程序时,它看起来如下所示:

enter image description here

正如您所看到的,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个项目时),他们都包含第一个元素的图像:

enter image description here

我认为问题可能出在drawingContext.DrawRectangle()的位置,因为我的矩形坐标总是相同的。所以我尝试将其更改为以下内容,我认为应该可以使用,但由于某种原因,它只会生成一个带有第一个UserControl和4个空PNG的PNG。

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

结果:

enter image description here

我在这里做错了什么?

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

1 个答案:

答案 0 :(得分:1)

请检查以下两种方法。我测试了它,它运行得很好。 1.首先,找到你的孩子物品控制 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;
        }

<强> RESULT enter image description here