I've found a new twist on the "Visual to RenderTargetBitmap" question!
I'm rendering previews of WPF stuff for a designer. That means I need to take a WPF visual and render it to a bitmap without that visual ever being displayed. Got a nice little method to do it like to see it here it goes
private static BitmapSource CreateBitmapSource(FrameworkElement visual)
{
Border b = new Border { Width = visual.Width, Height = visual.Height };
b.BorderBrush = Brushes.Black;
b.BorderThickness = new Thickness(1);
b.Background = Brushes.White;
b.Child = visual;
b.Measure(new Size(b.Width, b.Height));
b.Arrange(new Rect(b.DesiredSize));
RenderTargetBitmap rtb = new RenderTargetBitmap(
(int)b.ActualWidth,
(int)b.ActualHeight,
96,
96,
PixelFormats.Pbgra32);
// intermediate step here to ensure any VisualBrushes are rendered properly
DrawingVisual dv = new DrawingVisual();
using (var dc = dv.RenderOpen())
{
var vb = new VisualBrush(b);
dc.DrawRectangle(vb, null, new Rect(new Point(), b.DesiredSize));
}
rtb.Render(dv);
return rtb;
}
Works fine, except for one leeetle thing... if my FrameworkElement has a VisualBrush, that brush doesn't end up in the final rendered bitmap. Something like this:
<UserControl.Resources>
<VisualBrush
x:Key="LOLgo">
<VisualBrush.Visual>
<!-- blah blah -->
<Grid
Background="{StaticResource LOLgo}">
<!-- yadda yadda -->
Everything else renders to the bitmap, but that VisualBrush just won't show. The obvious google solutions have been attempted and have failed. Even the ones that specifically mention VisualBrushes missing from RTB'd bitmaps.
I have a sneaky suspicion this might be caused by the fact that its a Resource, and that lazy resource isn't being inlined. So a possible fix would be to, somehow(???), force resolution of all static resource references before rendering. But I have absolutely no idea how to do that.
Anybody have a fix for this?
You have two problems:
The immediate cause of your problem is failure to flush the Dispatcher queue, since VisualBrush uses it, but you will probably run into the PresentationSource problem before long so I would fix both of these.
Here is how I do it:
FYI, StaticResource lookup is never delayed under any circumstances: It is processed the moment the XAML is loaded and immediately replaced with the value retrieved from the ResourceDictionary. The only way StaticResource could possibly be related is if it picked up the wrong resource because two resources had the same key. I just thought I should explain this -- it has nothing to do with your actual problem.
Well to inline it, you could just do something like this:
If that doesn't work, my guess would be that it must be something specific with the
Visual
instance you are using (and that will require further code to better diagnose).