我在“Visual to RenderTargetBitmap”问题上找到了新的转折!
我正在为设计师呈现WPF的预览。这意味着我需要获取WPF视觉效果并将其渲染为位图,而不会显示该视觉效果。有一个很好的小方法来做它喜欢在这里看到它
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;
}
工作正常,除了一个leeetle事情...如果我的FrameworkElement有一个VisualBrush,那个画笔不会最终在最终渲染的位图中。像这样:
<UserControl.Resources>
<VisualBrush
x:Key="LOLgo">
<VisualBrush.Visual>
<!-- blah blah -->
<Grid
Background="{StaticResource LOLgo}">
<!-- yadda yadda -->
其他所有内容都呈现给位图,但VisualBrush不会显示。已经尝试了明显的谷歌解决方案并且失败了。甚至那些特别提到RTB'd位图中缺少VisualBrushes的那些。
我有一种偷偷摸摸的怀疑,这可能是因为它是一个资源,而且懒惰的资源没有被内联。因此,一种可能的解决方法是,以某种方式(???),在渲染之前强制解析所有静态资源引用。但我完全不知道该怎么做。
有人对此有解决方法吗?
答案 0 :(得分:14)
你有两个问题:
问题的直接原因是无法刷新Dispatcher队列,因为VisualBrush使用它,但您很快就会遇到PresentationSource问题,所以我会解决这两个问题。
我是这样做的:
// Create the container
var container = new Border
{
Child = contentVisual,
Background = Brushes.White,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1),
};
// Measure and arrange the container
container.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
container.Arrange(new Rect(container.DesiredSize));
// Temporarily add a PresentationSource if none exists
using(var temporaryPresentationSource = new HwndSource(new HwndSourceParameters()) { RootVisual = (VisualTreeHelper.GetParent(container)==null ? container : null) })
{
// Flush the dispatcher queue
Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));
// Render to bitmap
var rtb = new RenderTargetBitmap((int)b.ActualWidth, (int)b.ActualHeight, 96, 96, PixelFormats.Pbgra32);
rtb.Render(container);
return rtb;
}
仅供参考,StaticResource查找在任何情况下都不会延迟:它在加载XAML时立即处理,并立即替换为从ResourceDictionary检索的值。静态资源可以可能相关的唯一方式是,如果它选择了错误的资源,因为两个资源具有相同的密钥。我只是想我应该解释一下 - 它与你的实际问题无关。
答案 1 :(得分:0)
好吧内联它,你可以做这样的事情:
<Grid>
<Grid.Background>
<VisualBrush>
<VisualBrush.Visual>
<!-- blah blah -->
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
</Grid>
如果这不起作用,我的猜测是它必须是您正在使用的Visual
实例的特定内容(并且需要更多代码才能更好地进行诊断)。