WPF C#

// (c) Copyright Cory Plotts.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows;
namespace Snoop
{
  class VisualCaptureUtil
  {
    public static void SaveVisual(Visual visual, int dpi, string filename)
    {
      // sometimes RenderTargetBitmap doesn't render the Visual or doesn't render the Visual properly
      // below i am using the trick that jamie rodriguez posted on his blog
      // where he wraps the Visual inside of a VisualBrush and then renders it.
      // http://blogs.msdn.com/b/jaimer/archive/2009/07/03/rendertargetbitmap-tips.aspx
      if (visual == null)
        return;
      Rect bounds;
      UIElement uiElement = visual as UIElement;
      if (uiElement != null)
      {
        bounds = new Rect(new Size((int)uiElement.RenderSize.Width, (int)uiElement.RenderSize.Height));
      }
      else
      {
        bounds = VisualTreeHelper.GetDescendantBounds(visual);
      }
      double sizeFactor = dpi / BaseDpi;
      RenderTargetBitmap rtb =
        new RenderTargetBitmap
        (
          (int)(bounds.Width * sizeFactor),
          (int)(bounds.Height * sizeFactor),
          dpi,
          dpi,
          PixelFormats.Pbgra32
        );
      DrawingVisual dv = new DrawingVisual();
      using (DrawingContext ctx = dv.RenderOpen())
      {
        VisualBrush vb = new VisualBrush(visual);
        ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
      }
      rtb.Render(dv);
      SaveRTBAsPNG(rtb, filename);
    }
    private static void SaveRTBAsPNG(RenderTargetBitmap bitmap, string filename)
    {
      var pngBitmapEncoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
      pngBitmapEncoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(bitmap));
      using (var fileStream = System.IO.File.Create(filename))
        pngBitmapEncoder.Save(fileStream);
    }
    private const double BaseDpi = 96;
  }
}