Save WPF/Xaml controls to Bitmaps

February 17th, 2012 by admin Leave a reply »

I don’t know if you have ever had the need to save an image of a Xaml/Wpf control but I did recently in a project. The method I have below will do just this:

public List<Bitmap> ExportToPng(List<object> objects) {
            var images = new List<Bitmap>();
            // iterate wpf objects, saving current canvas transform
            foreach (object o in objects) {
                Transform transform = c.LayoutTransform;

                // reset current transform (in case it is scaled or rotated)
                c.LayoutTransform = null;

                // Create a render bitmap and push the surface to it
                var renderBitmap =
                new RenderTargetBitmap(
                (int)c.ActualWidth,
                (int)c.ActualHeight,
                96d,
                96d,
                PixelFormats.Pbgra32);

                renderBitmap.Render(c);
                System.Drawing.Image ImageWork;
                // Create a memory stream for using image
                using (var stm = new MemoryStream()) {
                    // Use png encoder for our data
                    var encoder = new PngBitmapEncoder();

                    // push the rendered bitmap to it
                    encoder.Frames.Add(BitmapFrame.Create(renderBitmap));

                    // save the data to the stream
                    encoder.Save(stm);
                    ImageWork = System.Drawing.Image.FromStream(stm);
                    images.Add(ImageWork as Bitmap);
                }
                // Restore previously saved layout
                c.LayoutTransform = transform;
            }
            return images;
        }

The method does take an array of objects, of course you could modify it to only do one at a time but I had several I needed in my example. The key thing here is that in your xaml code, make sure you have your control in just a single stackpanel, or a stackpanel per control. I found that when I had several controls in a single stackpanel, it was only grabbing the first one, the rest of the controls were not getting generated. This would be a really nice feature that Microsoft could provide to all their controls because I know I am not the only person that has wanted this functionality but had to write this hack in get it accomplished.

Advertisement

Leave a Reply