Export diagram to image

Once you or your users have drawn a diagram with the diagram designer, it might be possible they want to export the diagram to an image to use it i.e. in a worddocument. Fortunatly WPF helps us alot with this. Lets begin with some basics of saving WPF Elements to an image.

Rendering a UIElement to an image
WPF provides us the class RenderTargetBitmap, with which we can render a UIElement to a Bitmap. As a bitmap very likely is not the format you’d like to have, we’ll use the class PngBitmapEncoder as well to save our image as png.

Implementation of the export-method

Before we begin – you’ll see, that I pass the filePath directly into the method. I do this for simplicity only. Normally this is bad practice, as testing the method becomes difficult. Instead you should pass a Stream into the method in your implementation.

Follow these steps to implement an export to image for the WPF Diagram Designer:

  1. Create a new class with the name DiagramDesignerExporter
  2. Next we need a method, which passes the UIElement to the method, which shall be rendered, as well as the path where the image should be saved to. In our case the UIElement will be the DesignerCanvas, but in fact you could pass any UIElement to it.Add the static method with the following signature to the class DiagramDesignerExporter:
    public static void ExportToPng(UIElement target, string ImagePath)
    
  3. To export only the parts which contain DesignerItems on the diagram, we need to first call measure and then arrange on the target. If we wouldn’t, your export would have unnecessary whitespace borders. Add the following code to the method ExportToPng:
    // Prepare target-layout
    Size size = target.RenderSize;
    target.Measure(size);
    target.Arrange(new Rect(size));
    
  4. Now we use the RenderTargetBitmap to render the UIElement to a bitmap. We pass the constructor the Width, Height, DIP (dots per inch) for x- and y-axis and finally the pixelformat. 32bit in our example. Add the following code to the method ExportToPng:
    // Render diagram to bitmap
    RenderTargetBitmap renderBitmap =
    	new RenderTargetBitmap(
    		(int)size.Width,
    		(int)size.Height,
    		96, 96,
    		PixelFormats.Pbgra32);
    renderBitmap.Render(target);
    
  5. The renderBitmap-object can now be passed to the PngBitmapEncoder. Unfortunatly this can not be done directly. We need to create a BitmapFrame, which is an intermediate imagedata-format, which can be used by encoders and decoders. Add the following code to the method ExportToPng:
    // Convert bitmap to png
    PngBitmapEncoder encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
    
  6. The final step is to save the image to the disk (or wherever you like). The PngBitmapEncoder provides the possibility to save to a stream. In this tutorial we’ll pass a StreamWriter to it, to save the image to the path we passed into the method. Add the following code to the method ExportToPng:
    using (FileStream fileStream = new FileStream(ImagePath, FileMode.Create))
    {
    	encoder.Save(fileStream);
    }
    

Executing the export-method

With this you have the diagram-export method completed. Now how and where can you call it? Let me answer the first question first. You can call it like this:

SelectionService.ClearSelection(); // Unselect DesignerItems
DiagramDesignerExporter.ExportToPng(<DesignerCanvas-Object>, "<YourFullFilePath>");

Where you want to call the ExportToPng-method depends a lot on what kind of application you build. If you just enhance the original WPF Diagram Designer, then you most likely add a new button to the Ribbon-Toolbar and add a new method into the file DesignerCanvas.Commands.cs. If you do so, you can call the method simply like this:

DiagramDesignerExporter.ExportToPng(this, <YourFullFilePath>);

If you like it, please share it or leave a comment, to encourage me to write more parts :-)