我有一个图表,我正在向用户显示,我希望能够将图表作为图像导出到磁盘,以便他们可以在应用程序之外使用它(用于演示文稿或其他东西)。
我已经设法使用PngBitmapEncoder和RenderTargetBitmap来获得基本的想法,但我得到的图像是小到可以使用的方式,我希望得到更大的图像。
我试图简单地增加我想要渲染的控件的高度和宽度,但是父级似乎可以直接控制渲染大小。从这里我试图在内存中复制UIElement但是然后渲染大小为(0,0)并且当我尝试使用方法来渲染它时,例如Measure()Arrange()和UpdateLayout()它们会抛出异常需要解耦父级来调用它们,但是因为它在内存中而没有呈现,所以不应该有父级吗?
这一切都是通过Visiblox图表API
完成的这是我目前所拥有的,除了它不起作用:(
var width = 1600;
var height = 1200;
var newChart = new Chart { Width = width, Height = height, Title = chart.Title, XAxis = chart.XAxis, YAxis = chart.YAxis, Series = chart.Series};
Debug.WriteLine(newChart.RenderSize);
var size = new Size(width, height);
newChart.Measure(size);
newChart.Arrange(new Rect(size));
newChart.UpdateLayout();
Debug.WriteLine(newChart.RenderSize);
var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(newChart);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
using (var stream = fileDialog.OpenFile())
encoder.Save(stream);
我已经离得更近了,它现在将图形背景渲染为轴'等等,但实际上并没有绘制实际的线条。以下是更新的来源
public static void RenderChartToImage(Chart elementToRender, string filename)
{
if (elementToRender == null)
return;
Debug.Write(elementToRender.RenderSize);
var clone = new Chart();
clone.Width = clone.Height = double.NaN;
clone.HorizontalAlignment = HorizontalAlignment.Stretch;
clone.VerticalAlignment = VerticalAlignment.Stretch;
clone.Margin = new Thickness();
clone.Title = elementToRender.Title;
clone.XAxis = new DateTimeAxis();
clone.YAxis = new LinearAxis() { Range = Range<double>)elementToRender.YAxis.Range};
foreach (var series in elementToRender.Series)
{
var lineSeries = new LineSeries
{
LineStroke = (series as LineSeries).LineStroke,
DataSeries = series.DataSeries
};
clone.Series.Add(lineSeries);
}
var size = new Size(1600, 1200);
clone.Measure(size);
clone.Arrange(new Rect(size));
clone.UpdateLayout();
Debug.Write(clone.RenderSize);
var height = (int)clone.ActualHeight;
var width = (int)clone.ActualWidth;
var renderer = new RenderTargetBitmap(width, height, 96d, 96d, PixelFormats.Pbgra32);
renderer.Render(clone);
var pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(renderer));
using (var file = File.Create(filename))
{
pngEncoder.Save(file);
}
}
所以我得到这样的东西:
虽然很大,但没有用,因为它没有任何图表。
答案 0 :(得分:3)
http://www.visiblox.com/blog/2011/05/printing-visiblox-charts
我遗漏的要点是
InvalidationHandler.ForceImmediateInvalidate = true;
在我将图表渲染到内存中之前进行设置,然后在完成后将其还原。从那里开始顺风顺水:D
答案 1 :(得分:2)
RenderTargetBitmap DrawToImage<T>(T source, double scale) where T:FrameworkElement
{
var clone = Clone(source);
clone.Width = clone.Height = Double.NaN;
clone.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
clone.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
clone.Margin = new Thickness();
var size = new Size(source.ActualWidth * scale, source.ActualHeight * scale);
clone.Measure(size);
clone.Arrange(new Rect(size));
var renderBitmap = new RenderTargetBitmap((int)clone.ActualWidth, (int)clone.ActualHeight, 96, 96, PixelFormats.Pbgra32);
renderBitmap.Render(clone);
return renderBitmap;
}
static T Clone<T>(T source) where T:UIElement
{
if (source == null)
return null;
string xaml = XamlWriter.Save(source);
var reader = new StringReader(xaml);
var xmlReader = XmlTextReader.Create(reader, new XmlReaderSettings());
return (T)XamlReader.Load(xmlReader);
}
答案 2 :(得分:1)