27

I have the following code:

void Test()
{
    currentImage.Source = GetBitmap();
    RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default);
    rtb.Render(currentImage);
}

This code is supposed to render currentImage, which is an Image control in my xaml to a RenderTargetBitmap.

It doesn't work, rtb returns a blank image, the problem is currentImage didn't render itself yet and so this behavior is expected, I think...

To workaround this problem, I wrote this code:

void Test()
{
    currentImage.Source = GetBitmap();

    this.Dispatcher.BeginInvoke((Action)delegate()
    {
        RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default);
        rtb.Render(currentImage);
    }, System.Windows.Threading.DispatcherPriority.Render, null);

}

Basically, I wait for currentImage to be rendered and then I can get it properly rendered to my RenderTargetBitmap.

Is there any way to make it work without using this workaround? Force the Image control to render in memory maybe?

thanks!

Schwertz
  • 1,073
  • 2
  • 13
  • 13
  • Note: If you have a complex layout and you are showing and hiding elements with converters you may end up with an incorrect final layout. This is what I had to do to work around it : http://stackoverflow.com/questions/41966704/wpf-xaml-control-converted-to-an-image-has-incorrect-layout/41966743#41966743 – Simon_Weaver Jan 31 '17 at 20:18

2 Answers2

44

use a ViewBox to render in memory

Grid grid = new System.Windows.Controls.Grid() { Background = Brushes.Blue, Width = 200, Height = 200 };
Viewbox viewbox = new Viewbox();
viewbox.Child = grid; //control to render
viewbox.Measure(new System.Windows.Size(200, 200));
viewbox.Arrange(new Rect(0, 0, 200, 200));
viewbox.UpdateLayout();
RenderTargetBitmap render = new RenderTargetBitmap(200, 200, 150, 150, PixelFormats.Pbgra32);
render.Render(viewbox);
Daniel Pamich
  • 971
  • 10
  • 7
  • Thank you so much for this solution! I've been struggling with this for a while but didn't know about the ViewBox trick to render in memory. Thank you!! – Kilhoffer Jan 17 '12 at 21:48
  • 2
    It is possible to use other "containers" (anything that derives from Panel) to achieve the same result. A ViewBox will scale the content while Panels won't. – Jonas Rembratt Aug 24 '12 at 14:43
13

I think this is a BETTER answer .
The viewbox didn't work completely as expected, and it turned out to be an unnecessary overhead.

Here is a copy of that answer (instead of just link)


You need to force a render of the item, or wait for the item to be rendered. You can then use the ActualHeight and ActualWidth properties.

To force a render:

  MenuItem item = new MenuItem();
  item.Header = "bling";
  item.Icon = someIcon;
  //Force render
  item.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
  item.Arrange(new Rect(item.DesiredSize));

In this example the MenuItem has not been given an explicit height or width. However, forcing the render will render it taking the supplied header text and icon into consideration.

Community
  • 1
  • 1
Martin Lottering
  • 1,624
  • 19
  • 31