代码之家  ›  专栏  ›  技术社区  ›  Sach

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

  •  1
  • Sach  · 技术社区  · 6 年前

    在我的WPF应用程序中,我有一个 ScrollViewer 动态填充的 DataBinding 以及使用 UserControl . 想象一下我的 用户控件 是仅包含标签的简单内容,标签中显示的值来自列表。因此,当我运行应用程序时,它如下所示:

    enter image description here

    如您所见,有多个 用户控件 每个都具有动态填充的不同值。我的目标是导出 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() 因为我的矩形坐标总是一样的。所以我尝试将其更改为以下内容,我认为应该可以,但出于某种原因,它只会生成一个PNG 用户控件 和4个空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 回复  |  直到 6 年前
        1
  •  1
  •   Gaurang Dave    6 年前

    请检查以下两种方法。我对它进行了测试,效果很好。 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;
            }
    

    结果 enter image description here