Create WPF element offscreen and render to bitmap
Asked Answered
H

1

22

I can't understand why this doesn't work, or what I need to get it to work.

To repro, create a simple WPF application and replace the main window's constructor thusly:

    public MainWindow()
    {
        InitializeComponent();

        // simple visual definition
        var grid = new Grid { Width = 300, Height = 300 };
        var text = new TextBlock 
                       { 
                         Text = "Y DON'T I WORK???", 
                         FontSize = 100, 
                         FontWeight = 
                         FontWeights.Bold 
                       };
        grid.Children.Add(text);

        // update the layout so everything is awesome cool
        grid.Measure(grid.DesiredSize);
        grid.Arrange(new Rect(grid.DesiredSize));
        grid.UpdateLayout();

        // create a BitmapSource from the visual
        var rtb = new RenderTargetBitmap(
                                    (int)grid.Width,
                                    (int)grid.Height,
                                    96,
                                    96,
                                    PixelFormats.Pbgra32);
        rtb.Render(grid);

        // Slap it in the window
        this.Content = new Image { Source = rtb, Width = 300, Height = 300 };
    }

This results in an empty image. If I save the RTB to disk as a PNG its the correct size but transparent.

If, however, I do this with a visual that's been displayed on screen, it works fine.

How can I render a visual I've constructed offscreen to a bitmap?

Hightoned answered 9/12, 2009 at 21:43 Comment(0)
G
27

Because elements don't have a desired size until you measure them. You were telling the Grid to size itself with an available space of 0x0. Change your code to:

grid.Measure(new Size(grid.Width, grid.Height));
grid.Arrange(new Rect(new Size(grid.Width, grid.Height)));

(The call to UpdateLayout is unneeded.)

Genova answered 9/12, 2009 at 23:49 Comment(4)
Son of a........ I checked DesiredSize once way back when I started to try to accomplish this and it wasn't 0,0 (who knows why) and never checked it again. Thanks!Hightoned
We just found out that if you have ItemsControls bound to their ItemsSources inside the control you're rendering offscreen it seems that you do have to call UpdateLayout() or they don't render any items.Rattoon
UpdateLayout seems to be necessary to render DiffuseMaterial, too. It must do more than its name implies.Dude
Awesome. You just saved my life.Diminuendo

© 2022 - 2024 — McMap. All rights reserved.