我想使用RenderTargetBitmap功能将XAML控件呈现给PNG文件。到目前为止,这很有效。
但是如果XAML包含任何图像,则这些图像不会在PNG文件中呈现。 这是我的XAML:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="LayoutRoot"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="336"
d:DesignWidth="336"
Background="DarkGray">
<TextBlock Text="This is my Text"
FontSize="35"
HorizontalAlignment="Center" />
<Image Source="http://www.myurl.com/image.png"
Height="200" /></Grid>
这是我的代码:
private BitmapSource RenderToBitmap(FrameworkElement target)
{
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)target.ActualWidth,
(int)target.ActualHeight,
96, 96, PixelFormats.Pbgra32);
DrawingVisual visual = new DrawingVisual();
using (DrawingContext context = visual.RenderOpen())
{
VisualBrush brush = new VisualBrush(target);
context.DrawRectangle(brush, null, new Rect(new Point(), bounds.Size));
}
renderBitmap.Render(visual);
return renderBitmap;
}
还尝试使用像“/Assets/image.png”这样的参考图像和资源。每次在渲染的PNG文件中缺少图像时。
答案 0 :(得分:2)
首先,您要渲染目标,但ImageControl异步加载BitmapSource,此时尚未准备就绪。如果您要等到ImageControl完成加载其源代码,您将得到您期望的结果。有趣的是,ImageControl在完成加载时不会通知您。
因此,短回答将是: 如果要将现有和已加载的可视化渲染到图像,只需等待嵌入的图像控件加载即可。
像这样:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
img.LayoutUpdated += img_LayoutUpdated;
}
void img_LayoutUpdated(object sender, EventArgs e)
{
img.LayoutUpdated -= img_LayoutUpdated;
var rt = RenderToBitmap(img);
Save(rt);
}
据我所知,没有简单的方法可以强制ImageControl加载其源代码。当ImageControl抛出“Loaded”事件时,并不意味着图像被加载。如果你有ImageControl.Source创建为BitmapImage,你可以做这样的事情:
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.DecodePixelHeight = 100;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.UriSource = new Uri(@"http://www.myurl.com/image.png");
bi.EndInit();
bi.DownloadCompleted += bi_DownloadCompleted; //will be ready to be saved to image when event will fire
img.Source = bi;
或者像这样自己下载图片
WebClient wc = new WebClient();
using (MemoryStream stream = new MemoryStream(wc.DownloadData(@"http://www.google.ru/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png")))
{
BitmapImage myBitmapImage = new BitmapImage();
myBitmapImage.BeginInit();
myBitmapImage.StreamSource = stream;
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
img.Source = myBitmapImage;
// ready to be saved to image
}
但在我看来,它并不适合你
如果您的目的是在内存中呈现视觉效果,那么您应该看看这个问题: Drawing a WPF UserControl with DataBinding to an Image