[ACCEPTED]-How to render a WPF UserControl to a bitmap without creating a window-graphics

Accepted answer
Score: 70

Have you tried spinning up an instance of 3 the user control and doing something like 2 this:

UserControl control = new UserControl1();

control.Measure(new Size(300, 300));
control.Arrange(new Rect(new Size(300,300)));

RenderTargetBitmap bmp = new RenderTargetBitmap(300, 300, 96, 96, PixelFormats.Pbgra32);


var encoder = new PngBitmapEncoder();


using (Stream stm = File.Create(@"c:\test.png"))

It looks like you need to Measure, Arrange. This 1 worked for me.

Score: 7

Ended up using an HwndHost with no actual 1 window.

void cwind()
        Application myapp = new Application();
        mrenderer = new WPFRenderer();
        mrenderer.Width = 256;
        mrenderer.Height = 256;

        HwndSourceParameters myparms = new HwndSourceParameters();
        HwndSource msrc = new HwndSource(myparms);
        myparms.HwndSourceHook = new HwndSourceHook(ApplicationMessageFilter);

        msrc.RootVisual = mrenderer;
    static IntPtr ApplicationMessageFilter(
IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled)
        return IntPtr.Zero;
Score: 4

Apparently, if you call control.UpdateLayout() after measuring 2 and arranging, the user control doesn't 1 need to be in any window.

Score: 1

Based on IDWMaster's solution I did it a 4 bit differently using the System.Windows.Forms.UserControl. Otherwise the 3 bindings were not up-to-date when the export 2 to bitmap happened. This works for me (this is 1 the WPF control to render):

System.Windows.Forms.UserControl controlContainer = new System.Windows.Forms.UserControl();
controlContainer.Width = width;
controlContainer.Height = height;
controlContainer.Load += delegate(object sender, EventArgs e)
        using (FileStream fs = new FileStream(path, FileMode.Create))
            RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
            BitmapEncoder encoder = new PngBitmapEncoder();
    }, DispatcherPriority.Background);

controlContainer.Controls.Add(new ElementHost() { Child = this, Dock = System.Windows.Forms.DockStyle.Fill });
IntPtr handle = controlContainer.Handle;

More Related questions