Force rendering of a WPF control in memory

2019-01-07 14:04发布

问题:

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!

回答1:

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);


回答2:

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.